aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManuel Novoa III <mjn3@codepoet.org>2002-09-12 14:52:26 +0000
committerManuel Novoa III <mjn3@codepoet.org>2002-09-12 14:52:26 +0000
commit4d0884a1eaefb7af31f8039f3aa9128362535716 (patch)
treea685c539b63b81ee6689d9738c588555dc4ecb44
parent7829b8d067225e6ab90ba289b2c9375349204acd (diff)
downloadbusybox-w32-4d0884a1eaefb7af31f8039f3aa9128362535716.tar.gz
busybox-w32-4d0884a1eaefb7af31f8039f3aa9128362535716.tar.bz2
busybox-w32-4d0884a1eaefb7af31f8039f3aa9128362535716.zip
Apply vodz's last_patch53.gz (bb_asprintf.c) and last_patch54.gz
(arith.c).
-rw-r--r--libbb/arith.c141
-rw-r--r--libbb/bb_asprintf.c74
2 files changed, 60 insertions, 155 deletions
diff --git a/libbb/arith.c b/libbb/arith.c
index d79501cc4..3e107126a 100644
--- a/libbb/arith.c
+++ b/libbb/arith.c
@@ -140,8 +140,7 @@ typedef char operator;
140#define TOK_REM tok_decl(10,2) 140#define TOK_REM tok_decl(10,2)
141 141
142/* For now all unary operators have the same precedence, and that's used to 142/* For now all unary operators have the same precedence, and that's used to
143 * identify them as unary operators 143 * identify them as unary operators */
144 */
145#define UNARYPREC 14 144#define UNARYPREC 14
146#define TOK_BNOT tok_decl(UNARYPREC,0) 145#define TOK_BNOT tok_decl(UNARYPREC,0)
147#define TOK_NOT tok_decl(UNARYPREC,1) 146#define TOK_NOT tok_decl(UNARYPREC,1)
@@ -157,82 +156,68 @@ typedef char operator;
157 156
158/* "applying" a token means performing it on the top elements on the integer 157/* "applying" a token means performing it on the top elements on the integer
159 * stack. For a unary operator it will only change the top element, but a 158 * stack. For a unary operator it will only change the top element, but a
160 * binary operator will pop two arguments and push a result 159 * binary operator will pop two arguments and push a result */
161 */
162static short arith_apply(operator op, long *numstack, long **numstackptr) 160static short arith_apply(operator op, long *numstack, long **numstackptr)
163{ 161{
164 long numptr_val; 162 long numptr_val;
165 long *NUMPTR_M1; 163 long *NUMPTR_M1;
166 164
167 /* There is no operator that can work without arguments */ 165 if (NUMPTR == numstack) goto err; /* There is no operator that can work
168 if (NUMPTR == numstack) { 166 without arguments */
169 goto err;
170 }
171
172 NUMPTR_M1 = NUMPTR - 1; 167 NUMPTR_M1 = NUMPTR - 1;
173 if (op == TOK_UMINUS) { 168 if (op == TOK_UMINUS)
174 *NUMPTR_M1 *= -1; 169 *NUMPTR_M1 *= -1;
175 } else if (op == TOK_NOT) { 170 else if (op == TOK_NOT)
176 *NUMPTR_M1 = !(*NUMPTR_M1); 171 *NUMPTR_M1 = !(*NUMPTR_M1);
177 } else if (op == TOK_BNOT) { 172 else if (op == TOK_BNOT)
178 *NUMPTR_M1 = ~(*NUMPTR_M1); 173 *NUMPTR_M1 = ~(*NUMPTR_M1);
179 } else if (op != TOK_UPLUS) { 174 else if (op != TOK_UPLUS) {
180 /* Binary operators */ 175 /* Binary operators */
181 176 if (NUMPTR_M1 == numstack) goto err; /* ... and binary operators need two
182 /* ... and binary operators need two arguments */ 177 arguments */
183 if (NUMPTR_M1 == numstack) { 178 numptr_val = *--NUMPTR; /* ... and they pop one */
184 goto err;
185 }
186 /* ... and they pop one */
187 numptr_val = *--NUMPTR;
188
189 NUMPTR_M1 = NUMPTR - 1; 179 NUMPTR_M1 = NUMPTR - 1;
190 180 if (op == TOK_BOR)
191 if (op == TOK_BOR) {
192 *NUMPTR_M1 |= numptr_val; 181 *NUMPTR_M1 |= numptr_val;
193 } else if (op == TOK_OR) { 182 else if (op == TOK_OR)
194 *NUMPTR_M1 = numptr_val || *NUMPTR_M1; 183 *NUMPTR_M1 = numptr_val || *NUMPTR_M1;
195 } else if (op == TOK_BAND) { 184 else if (op == TOK_BAND)
196 *NUMPTR_M1 &= numptr_val; 185 *NUMPTR_M1 &= numptr_val;
197 } else if (op == TOK_AND) { 186 else if (op == TOK_AND)
198 *NUMPTR_M1 = *NUMPTR_M1 && numptr_val; 187 *NUMPTR_M1 = *NUMPTR_M1 && numptr_val;
199 } else if (op == TOK_EQ) { 188 else if (op == TOK_EQ)
200 *NUMPTR_M1 = (*NUMPTR_M1 == numptr_val); 189 *NUMPTR_M1 = (*NUMPTR_M1 == numptr_val);
201 } else if (op == TOK_NE) { 190 else if (op == TOK_NE)
202 *NUMPTR_M1 = (*NUMPTR_M1 != numptr_val); 191 *NUMPTR_M1 = (*NUMPTR_M1 != numptr_val);
203 } else if (op == TOK_GE) { 192 else if (op == TOK_GE)
204 *NUMPTR_M1 = (*NUMPTR_M1 >= numptr_val); 193 *NUMPTR_M1 = (*NUMPTR_M1 >= numptr_val);
205 } else if (op == TOK_RSHIFT) { 194 else if (op == TOK_RSHIFT)
206 *NUMPTR_M1 >>= numptr_val; 195 *NUMPTR_M1 >>= numptr_val;
207 } else if (op == TOK_LSHIFT) { 196 else if (op == TOK_LSHIFT)
208 *NUMPTR_M1 <<= numptr_val; 197 *NUMPTR_M1 <<= numptr_val;
209 } else if (op == TOK_GT) { 198 else if (op == TOK_GT)
210 *NUMPTR_M1 = (*NUMPTR_M1 > numptr_val); 199 *NUMPTR_M1 = (*NUMPTR_M1 > numptr_val);
211 } else if (op == TOK_LT) { 200 else if (op == TOK_LT)
212 *NUMPTR_M1 = (*NUMPTR_M1 < numptr_val); 201 *NUMPTR_M1 = (*NUMPTR_M1 < numptr_val);
213 } else if (op == TOK_LE) { 202 else if (op == TOK_LE)
214 *NUMPTR_M1 = (*NUMPTR_M1 <= numptr_val); 203 *NUMPTR_M1 = (*NUMPTR_M1 <= numptr_val);
215 } else if (op == TOK_MUL) { 204 else if (op == TOK_MUL)
216 *NUMPTR_M1 *= numptr_val; 205 *NUMPTR_M1 *= numptr_val;
217 } else if (op == TOK_ADD) { 206 else if (op == TOK_ADD)
218 *NUMPTR_M1 += numptr_val; 207 *NUMPTR_M1 += numptr_val;
219 } else if (op == TOK_SUB) { 208 else if (op == TOK_SUB)
220 *NUMPTR_M1 -= numptr_val; 209 *NUMPTR_M1 -= numptr_val;
221 } 210 else if(numptr_val==0) /* zero divisor check */
222 /* zero divisor check */
223 else if (numptr_val == 0) {
224 return -2; 211 return -2;
225 } else if (op == TOK_DIV) { 212 else if (op == TOK_DIV)
226 *NUMPTR_M1 /= numptr_val; 213 *NUMPTR_M1 /= numptr_val;
227 } else if (op == TOK_REM) { 214 else if (op == TOK_REM)
228 *NUMPTR_M1 %= numptr_val; 215 *NUMPTR_M1 %= numptr_val;
229 }
230 /* WARNING!!! WARNING!!! WARNING!!! */ 216 /* WARNING!!! WARNING!!! WARNING!!! */
231 /* Any new operators should be added BEFORE the zero divisor check! */ 217 /* Any new operators should be added BEFORE the zero divisor check! */
232 } 218 }
233 return 0; 219 return 0;
234 err: 220err: return(-1);
235 return (-1);
236} 221}
237 222
238static const char endexpression[] = ")"; 223static const char endexpression[] = ")";
@@ -242,7 +227,7 @@ static const char op_char[] = "!<>=|&*/%~()+-";
242static const char op_token[] = { 227static const char op_token[] = {
243 /* paired with equal */ 228 /* paired with equal */
244 TOK_NE, TOK_LE, TOK_GE, 229 TOK_NE, TOK_LE, TOK_GE,
245 /* paired with self -- note: ! is special-cased below */ 230 /* paired with self -- note: ! is special-cased below*/
246 TOK_ERROR, TOK_LSHIFT, TOK_RSHIFT, TOK_EQ, TOK_OR, TOK_AND, 231 TOK_ERROR, TOK_LSHIFT, TOK_RSHIFT, TOK_EQ, TOK_OR, TOK_AND,
247 /* singles */ 232 /* singles */
248 TOK_NOT, TOK_LT, TOK_GT, TOK_ERROR, TOK_BOR, TOK_BAND, 233 TOK_NOT, TOK_LT, TOK_GT, TOK_ERROR, TOK_BOR, TOK_BAND,
@@ -253,33 +238,34 @@ static const char op_token[] = {
253#define NUM_PAIR_EQUAL 3 238#define NUM_PAIR_EQUAL 3
254#define NUM_PAIR_SAME 6 239#define NUM_PAIR_SAME 6
255 240
256extern long arith(const char *expr, int *errcode) 241extern long arith (const char *expr, int *errcode)
257{ 242{
258 register char arithval; /* Current character under analysis */ 243 register char arithval; /* Current character under analysis */
259 operator lasttok, op; 244 operator lasttok, op;
260 unsigned char prec; 245 unsigned char prec;
246
261 const char *p = endexpression; 247 const char *p = endexpression;
262 size_t datasizes = strlen(expr); 248
249 size_t datasizes = strlen(expr) + 2;
263 250
264 /* Stack of integers */ 251 /* Stack of integers */
265 /* The proof that there can be no more than strlen(startbuf)/2+1 integers 252 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
266 * in any given correct or incorrect expression is left as an excersize to 253 * in any given correct or incorrect expression is left as an excersize to
267 * the reader. */ 254 * the reader. */
268 long *numstack = alloca(((datasizes + 1) / 2) * sizeof(long)); 255 long *numstack = alloca(((datasizes)/2)*sizeof(long)),
269 long *numstackptr = numstack; 256 *numstackptr = numstack;
270
271 /* Stack of operator tokens */ 257 /* Stack of operator tokens */
272 operator * stack = alloca((datasizes + 1) * sizeof(operator)); 258 operator *stack = alloca((datasizes) * sizeof(operator)),
273 operator * stackptr = stack; 259 *stackptr = stack;
274 260
275 /* start off with a left paren */ 261 *numstack = 0;
276 *stackptr++ = lasttok = TOK_LPAREN; 262 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
277 263
278 loop: 264 loop:
279 if ((arithval = *expr) == 0) { 265 if ((arithval = *expr) == 0) {
280 /* Null expression. */ 266 if (p == endexpression) { /* Null expression. */
281 if (p == endexpression) { 267 *errcode = 0;
282 return (*errcode = 0); 268 return *numstack;
283 } 269 }
284 270
285 /* This is only reached after all tokens have been extracted from the 271 /* This is only reached after all tokens have been extracted from the
@@ -292,7 +278,7 @@ extern long arith(const char *expr, int *errcode)
292 goto loop; /* and let the loop process it. */ 278 goto loop; /* and let the loop process it. */
293 } 279 }
294 /* At this point, we're done with the expression. */ 280 /* At this point, we're done with the expression. */
295 if (numstackptr != numstack + 1) { /* ... but if there isn't, it's bad */ 281 if (numstackptr != numstack+1) {/* ... but if there isn't, it's bad */
296 err: 282 err:
297 return (*errcode = -1); 283 return (*errcode = -1);
298 /* NOTREACHED */ 284 /* NOTREACHED */
@@ -300,12 +286,10 @@ extern long arith(const char *expr, int *errcode)
300 return *numstack; 286 return *numstack;
301 } else { 287 } else {
302 /* Continue processing the expression. */ 288 /* Continue processing the expression. */
303 /* Skip whitespace */
304 if (isspace(arithval)) { 289 if (isspace(arithval)) {
305 goto prologue; 290 goto prologue; /* Skip whitespace */
306 } 291 }
307 /* isdigit ? */ 292 if ((unsigned)arithval-'0' <= 9) /* isdigit */ {
308 if ((unsigned) arithval - '0' <= 9) {
309 *numstackptr++ = strtol(expr, (char **) &expr, 10); 293 *numstackptr++ = strtol(expr, (char **) &expr, 10);
310 lasttok = TOK_NUM; 294 lasttok = TOK_NUM;
311 goto loop; 295 goto loop;
@@ -315,21 +299,20 @@ extern long arith(const char *expr, int *errcode)
315 goto err; 299 goto err;
316 } 300 }
317#else 301#else
318 for (p = op_char; *p != arithval; p++) { 302 for ( p=op_char ; *p != arithval ; p++ ) {
319 if (!*p) { 303 if (!*p) {
320 goto err; 304 goto err;
321 } 305 }
322 } 306 }
323#endif 307#endif
324 p = op_token + (int) (p - op_char); 308 p = op_token + (int)(p - op_char);
325 ++expr; 309 ++expr;
326 if ((p >= op_token + NUM_PAIR_EQUAL) || (*expr != '=')) { 310 if ((p >= op_token + NUM_PAIR_EQUAL) || (*expr != '=')) {
327 p += NUM_PAIR_EQUAL; 311 p += NUM_PAIR_EQUAL;
328 if ((p >= op_token + NUM_PAIR_SAME + NUM_PAIR_EQUAL) 312 if ((p >= op_token + NUM_PAIR_SAME + NUM_PAIR_EQUAL)
329 || (*expr != arithval) || (arithval == '!')) { 313 || (*expr != arithval) || (arithval == '!')) {
330 --expr; 314 --expr;
331 /* single = */ 315 if (arithval == '=') { /* single = */
332 if (arithval == '=') {
333 goto err; 316 goto err;
334 } 317 }
335 p += NUM_PAIR_SAME; 318 p += NUM_PAIR_SAME;
@@ -338,11 +321,9 @@ extern long arith(const char *expr, int *errcode)
338 * a number, since it evaluates to one). Think about it. 321 * a number, since it evaluates to one). Think about it.
339 * It makes sense. */ 322 * It makes sense. */
340 if ((lasttok != TOK_NUM) 323 if ((lasttok != TOK_NUM)
341 && (p >= 324 && (p >= op_token + NUM_PAIR_SAME + NUM_PAIR_EQUAL
342 (op_token + NUM_PAIR_SAME + NUM_PAIR_EQUAL + 325 + sizeof(op_char) - 2)) {
343 sizeof(op_char) - 2))) { 326 p += 2; /* Unary plus or minus */
344 /* Unary plus or minus */
345 p += 2;
346 } 327 }
347 } 328 }
348 } 329 }
@@ -358,11 +339,8 @@ extern long arith(const char *expr, int *errcode)
358 /* Left paren is given the lowest priority so it will never be 339 /* Left paren is given the lowest priority so it will never be
359 * "applied" in this way */ 340 * "applied" in this way */
360 prec = PREC(op); 341 prec = PREC(op);
361 342 if ((prec > 0) && (prec != UNARYPREC)) { /* not left paren or unary */
362 /* not left paren or unary */ 343 if (lasttok != TOK_NUM) { /* binary op must be preceded by a num */
363 if ((prec > 0) && (prec != UNARYPREC)) {
364 /* binary op must be preceded by a num */
365 if (lasttok != TOK_NUM) {
366 goto err; 344 goto err;
367 } 345 }
368 while (stackptr != stack) { 346 while (stackptr != stack) {
@@ -372,10 +350,7 @@ extern long arith(const char *expr, int *errcode)
372 * tokens and apply them */ 350 * tokens and apply them */
373 if (stackptr[-1] == TOK_LPAREN) { 351 if (stackptr[-1] == TOK_LPAREN) {
374 --stackptr; 352 --stackptr;
375 353 lasttok = TOK_NUM; /* Any operator directly after a */
376 /* Any operator directly after a */
377 lasttok = TOK_NUM;
378
379 /* close paren should consider itself binary */ 354 /* close paren should consider itself binary */
380 goto prologue; 355 goto prologue;
381 } 356 }
@@ -383,9 +358,7 @@ extern long arith(const char *expr, int *errcode)
383 break; 358 break;
384 } 359 }
385 *errcode = ARITH_APPLY(*--stackptr); 360 *errcode = ARITH_APPLY(*--stackptr);
386 if (*errcode) { 361 if(*errcode) return *errcode;
387 return *errcode;
388 }
389 } 362 }
390 if (op == TOK_RPAREN) { 363 if (op == TOK_RPAREN) {
391 goto err; 364 goto err;
diff --git a/libbb/bb_asprintf.c b/libbb/bb_asprintf.c
index c0c5cdeda..9a71be7f5 100644
--- a/libbb/bb_asprintf.c
+++ b/libbb/bb_asprintf.c
@@ -7,83 +7,15 @@
7#include <stdarg.h> 7#include <stdarg.h>
8 8
9 9
10#ifdef TEST 10#include "libbb.h"
11extern void *xrealloc(void *p, size_t size);
12#else
13#include "libbb.h" /* busybox source */
14#endif
15 11
16 12
17/* Exchange glibc vasprintf - minimize allocate memory version */
18/* libc5 and uclibc have not vasprintf function */
19void bb_vasprintf(char **string_ptr, const char *format, va_list args)
20{
21 int bs = 128;
22 char stack_buff[128];
23 char *buff = stack_buff;
24 int done;
25
26 /* two or more loop, first - calculate memory size only */
27 while(1) {
28 done = vsnprintf (buff, bs, format, args);
29/* Different libc have different interpretation vsnprintf returned value */
30 if(done >= 0) {
31 if(done < bs && buff != stack_buff) {
32 /* allocated */
33 *string_ptr = buff;
34 return;
35 } else {
36 /* true calculate memory size */
37 bs = done+1;
38 }
39 } else {
40 /*
41 * Old libc. Incrementaly test.
42 * Exact not minimize allocate memory.
43 */
44 bs += 128;
45 }
46 buff = xrealloc((buff == stack_buff ? NULL : buff), bs);
47 }
48}
49
50void bb_asprintf(char **string_ptr, const char *format, ...) 13void bb_asprintf(char **string_ptr, const char *format, ...)
51{ 14{
52 va_list p; 15 va_list p;
53 16
54 va_start(p, format); 17 va_start(p, format);
55 bb_vasprintf(string_ptr, format, p); 18 if(vasprintf(string_ptr, format, p)<0)
19 error_msg_and_die(memory_exhausted);
56 va_end(p); 20 va_end(p);
57} 21}
58
59#ifdef TEST
60int main(int argc, char **argv)
61{
62 char *out_buf;
63 char big_buf[200];
64 int i;
65
66 bb_asprintf(&out_buf, "Hi!\nargc=%d argv[0]=%s\n", argc, argv[0]);
67 printf(out_buf);
68 free(out_buf);
69
70 for(i=0; i < sizeof(big_buf)-1; i++)
71 big_buf[i]='x';
72 big_buf[i]=0;
73 bb_asprintf(&out_buf, "Test Big\n%s\n", big_buf);
74 printf(out_buf);
75 free(out_buf);
76
77 return 0;
78}
79
80void *xrealloc(void *p, size_t size)
81{
82 void *p2 = realloc(p, size);
83 if(p2==0) {
84 fprintf(stderr, "TEST: memory_exhausted\n");
85 exit(1);
86 }
87 return p2;
88}
89#endif