diff options
author | Manuel Novoa III <mjn3@codepoet.org> | 2002-09-12 14:52:26 +0000 |
---|---|---|
committer | Manuel Novoa III <mjn3@codepoet.org> | 2002-09-12 14:52:26 +0000 |
commit | 4d0884a1eaefb7af31f8039f3aa9128362535716 (patch) | |
tree | a685c539b63b81ee6689d9738c588555dc4ecb44 | |
parent | 7829b8d067225e6ab90ba289b2c9375349204acd (diff) | |
download | busybox-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.c | 141 | ||||
-rw-r--r-- | libbb/bb_asprintf.c | 74 |
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 | */ | ||
162 | static short arith_apply(operator op, long *numstack, long **numstackptr) | 160 | static 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: | 220 | err: return(-1); |
235 | return (-1); | ||
236 | } | 221 | } |
237 | 222 | ||
238 | static const char endexpression[] = ")"; | 223 | static const char endexpression[] = ")"; |
@@ -242,7 +227,7 @@ static const char op_char[] = "!<>=|&*/%~()+-"; | |||
242 | static const char op_token[] = { | 227 | static 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 | ||
256 | extern long arith(const char *expr, int *errcode) | 241 | extern 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" |
11 | extern 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 */ | ||
19 | void 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 | |||
50 | void bb_asprintf(char **string_ptr, const char *format, ...) | 13 | void 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 | ||
60 | int 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 | |||
80 | void *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 | ||