diff options
-rw-r--r-- | miscutils/bc.c | 266 |
1 files changed, 133 insertions, 133 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c index ca9506929..5b48f84a1 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c | |||
@@ -2196,139 +2196,6 @@ static BcStatus bc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, | |||
2196 | return s; | 2196 | return s; |
2197 | } | 2197 | } |
2198 | 2198 | ||
2199 | static bool bc_num_strValid(const char *val, size_t base) | ||
2200 | { | ||
2201 | BcDig b; | ||
2202 | bool radix; | ||
2203 | |||
2204 | b = (BcDig)(base <= 10 ? base + '0' : base - 10 + 'A'); | ||
2205 | radix = false; | ||
2206 | for (;;) { | ||
2207 | BcDig c = *val++; | ||
2208 | if (c == '\0') | ||
2209 | break; | ||
2210 | if (c == '.') { | ||
2211 | if (radix) return false; | ||
2212 | radix = true; | ||
2213 | continue; | ||
2214 | } | ||
2215 | if (c < '0' || c >= b || (c > '9' && c < 'A')) | ||
2216 | return false; | ||
2217 | } | ||
2218 | return true; | ||
2219 | } | ||
2220 | |||
2221 | // Note: n is already "bc_num_zero()"ed, | ||
2222 | // leading zeroes in "val" are removed | ||
2223 | static void bc_num_parseDecimal(BcNum *n, const char *val) | ||
2224 | { | ||
2225 | size_t len, i; | ||
2226 | const char *ptr; | ||
2227 | bool zero; | ||
2228 | |||
2229 | len = strlen(val); | ||
2230 | if (len == 0) | ||
2231 | return; | ||
2232 | |||
2233 | zero = true; | ||
2234 | for (i = 0; val[i]; ++i) { | ||
2235 | if (val[i] != '0' && val[i] != '.') { | ||
2236 | zero = false; | ||
2237 | break; | ||
2238 | } | ||
2239 | } | ||
2240 | bc_num_expand(n, len); | ||
2241 | |||
2242 | ptr = strchr(val, '.'); | ||
2243 | |||
2244 | n->rdx = 0; | ||
2245 | if (ptr != NULL) | ||
2246 | n->rdx = (size_t)((val + len) - (ptr + 1)); | ||
2247 | |||
2248 | if (!zero) { | ||
2249 | i = len - 1; | ||
2250 | for (;;) { | ||
2251 | n->num[n->len] = val[i] - '0'; | ||
2252 | ++n->len; | ||
2253 | skip_dot: | ||
2254 | if ((ssize_t)--i == (ssize_t)-1) break; | ||
2255 | if (val[i] == '.') goto skip_dot; | ||
2256 | } | ||
2257 | } | ||
2258 | } | ||
2259 | |||
2260 | // Note: n is already "bc_num_zero()"ed, | ||
2261 | // leading zeroes in "val" are removed | ||
2262 | static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base) | ||
2263 | { | ||
2264 | BcStatus s; | ||
2265 | BcNum temp, mult, result; | ||
2266 | BcDig c = '\0'; | ||
2267 | unsigned long v; | ||
2268 | size_t i, digits; | ||
2269 | |||
2270 | for (i = 0; ; ++i) { | ||
2271 | if (val[i] == '\0') | ||
2272 | return; | ||
2273 | if (val[i] != '.' && val[i] != '0') | ||
2274 | break; | ||
2275 | } | ||
2276 | |||
2277 | bc_num_init_DEF_SIZE(&temp); | ||
2278 | bc_num_init_DEF_SIZE(&mult); | ||
2279 | |||
2280 | for (;;) { | ||
2281 | c = *val++; | ||
2282 | if (c == '\0') goto int_err; | ||
2283 | if (c == '.') break; | ||
2284 | |||
2285 | v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); | ||
2286 | |||
2287 | s = bc_num_mul(n, base, &mult, 0); | ||
2288 | if (s) goto int_err; | ||
2289 | bc_num_ulong2num(&temp, v); | ||
2290 | s = bc_num_add(&mult, &temp, n, 0); | ||
2291 | if (s) goto int_err; | ||
2292 | } | ||
2293 | |||
2294 | bc_num_init(&result, base->len); | ||
2295 | //bc_num_zero(&result); - already is | ||
2296 | bc_num_one(&mult); | ||
2297 | |||
2298 | digits = 0; | ||
2299 | for (;;) { | ||
2300 | c = *val++; | ||
2301 | if (c == '\0') break; | ||
2302 | digits++; | ||
2303 | |||
2304 | v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); | ||
2305 | |||
2306 | s = bc_num_mul(&result, base, &result, 0); | ||
2307 | if (s) goto err; | ||
2308 | bc_num_ulong2num(&temp, v); | ||
2309 | s = bc_num_add(&result, &temp, &result, 0); | ||
2310 | if (s) goto err; | ||
2311 | s = bc_num_mul(&mult, base, &mult, 0); | ||
2312 | if (s) goto err; | ||
2313 | } | ||
2314 | |||
2315 | s = bc_num_div(&result, &mult, &result, digits); | ||
2316 | if (s) goto err; | ||
2317 | s = bc_num_add(n, &result, n, digits); | ||
2318 | if (s) goto err; | ||
2319 | |||
2320 | if (n->len != 0) { | ||
2321 | if (n->rdx < digits) bc_num_extend(n, digits - n->rdx); | ||
2322 | } else | ||
2323 | bc_num_zero(n); | ||
2324 | |||
2325 | err: | ||
2326 | bc_num_free(&result); | ||
2327 | int_err: | ||
2328 | bc_num_free(&mult); | ||
2329 | bc_num_free(&temp); | ||
2330 | } | ||
2331 | |||
2332 | static void bc_num_printNewline(void) | 2199 | static void bc_num_printNewline(void) |
2333 | { | 2200 | { |
2334 | if (G.prog.nchars == G.prog.len - 1) { | 2201 | if (G.prog.nchars == G.prog.len - 1) { |
@@ -2492,6 +2359,139 @@ static BcStatus bc_num_stream(BcNum *n, BcNum *base) | |||
2492 | } | 2359 | } |
2493 | #endif | 2360 | #endif |
2494 | 2361 | ||
2362 | static bool bc_num_strValid(const char *val, size_t base) | ||
2363 | { | ||
2364 | BcDig b; | ||
2365 | bool radix; | ||
2366 | |||
2367 | b = (BcDig)(base <= 10 ? base + '0' : base - 10 + 'A'); | ||
2368 | radix = false; | ||
2369 | for (;;) { | ||
2370 | BcDig c = *val++; | ||
2371 | if (c == '\0') | ||
2372 | break; | ||
2373 | if (c == '.') { | ||
2374 | if (radix) return false; | ||
2375 | radix = true; | ||
2376 | continue; | ||
2377 | } | ||
2378 | if (c < '0' || c >= b || (c > '9' && c < 'A')) | ||
2379 | return false; | ||
2380 | } | ||
2381 | return true; | ||
2382 | } | ||
2383 | |||
2384 | // Note: n is already "bc_num_zero()"ed, | ||
2385 | // leading zeroes in "val" are removed | ||
2386 | static void bc_num_parseDecimal(BcNum *n, const char *val) | ||
2387 | { | ||
2388 | size_t len, i; | ||
2389 | const char *ptr; | ||
2390 | bool zero; | ||
2391 | |||
2392 | len = strlen(val); | ||
2393 | if (len == 0) | ||
2394 | return; | ||
2395 | |||
2396 | zero = true; | ||
2397 | for (i = 0; val[i]; ++i) { | ||
2398 | if (val[i] != '0' && val[i] != '.') { | ||
2399 | zero = false; | ||
2400 | break; | ||
2401 | } | ||
2402 | } | ||
2403 | bc_num_expand(n, len); | ||
2404 | |||
2405 | ptr = strchr(val, '.'); | ||
2406 | |||
2407 | n->rdx = 0; | ||
2408 | if (ptr != NULL) | ||
2409 | n->rdx = (size_t)((val + len) - (ptr + 1)); | ||
2410 | |||
2411 | if (!zero) { | ||
2412 | i = len - 1; | ||
2413 | for (;;) { | ||
2414 | n->num[n->len] = val[i] - '0'; | ||
2415 | ++n->len; | ||
2416 | skip_dot: | ||
2417 | if ((ssize_t)--i == (ssize_t)-1) break; | ||
2418 | if (val[i] == '.') goto skip_dot; | ||
2419 | } | ||
2420 | } | ||
2421 | } | ||
2422 | |||
2423 | // Note: n is already "bc_num_zero()"ed, | ||
2424 | // leading zeroes in "val" are removed | ||
2425 | static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base) | ||
2426 | { | ||
2427 | BcStatus s; | ||
2428 | BcNum temp, mult, result; | ||
2429 | BcDig c = '\0'; | ||
2430 | unsigned long v; | ||
2431 | size_t i, digits; | ||
2432 | |||
2433 | for (i = 0; ; ++i) { | ||
2434 | if (val[i] == '\0') | ||
2435 | return; | ||
2436 | if (val[i] != '.' && val[i] != '0') | ||
2437 | break; | ||
2438 | } | ||
2439 | |||
2440 | bc_num_init_DEF_SIZE(&temp); | ||
2441 | bc_num_init_DEF_SIZE(&mult); | ||
2442 | |||
2443 | for (;;) { | ||
2444 | c = *val++; | ||
2445 | if (c == '\0') goto int_err; | ||
2446 | if (c == '.') break; | ||
2447 | |||
2448 | v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); | ||
2449 | |||
2450 | s = bc_num_mul(n, base, &mult, 0); | ||
2451 | if (s) goto int_err; | ||
2452 | bc_num_ulong2num(&temp, v); | ||
2453 | s = bc_num_add(&mult, &temp, n, 0); | ||
2454 | if (s) goto int_err; | ||
2455 | } | ||
2456 | |||
2457 | bc_num_init(&result, base->len); | ||
2458 | //bc_num_zero(&result); - already is | ||
2459 | bc_num_one(&mult); | ||
2460 | |||
2461 | digits = 0; | ||
2462 | for (;;) { | ||
2463 | c = *val++; | ||
2464 | if (c == '\0') break; | ||
2465 | digits++; | ||
2466 | |||
2467 | v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); | ||
2468 | |||
2469 | s = bc_num_mul(&result, base, &result, 0); | ||
2470 | if (s) goto err; | ||
2471 | bc_num_ulong2num(&temp, v); | ||
2472 | s = bc_num_add(&result, &temp, &result, 0); | ||
2473 | if (s) goto err; | ||
2474 | s = bc_num_mul(&mult, base, &mult, 0); | ||
2475 | if (s) goto err; | ||
2476 | } | ||
2477 | |||
2478 | s = bc_num_div(&result, &mult, &result, digits); | ||
2479 | if (s) goto err; | ||
2480 | s = bc_num_add(n, &result, n, digits); | ||
2481 | if (s) goto err; | ||
2482 | |||
2483 | if (n->len != 0) { | ||
2484 | if (n->rdx < digits) bc_num_extend(n, digits - n->rdx); | ||
2485 | } else | ||
2486 | bc_num_zero(n); | ||
2487 | |||
2488 | err: | ||
2489 | bc_num_free(&result); | ||
2490 | int_err: | ||
2491 | bc_num_free(&mult); | ||
2492 | bc_num_free(&temp); | ||
2493 | } | ||
2494 | |||
2495 | static BcStatus bc_num_parse(BcNum *n, const char *val, BcNum *base, | 2495 | static BcStatus bc_num_parse(BcNum *n, const char *val, BcNum *base, |
2496 | size_t base_t) | 2496 | size_t base_t) |
2497 | { | 2497 | { |