diff options
-rw-r--r-- | miscutils/bc.c | 88 |
1 files changed, 43 insertions, 45 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c index 71b419d8f..c36486414 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c | |||
@@ -2199,49 +2199,45 @@ static BcStatus bc_num_binary(BcNum *a, BcNum *b, BcNum *c, size_t scale, | |||
2199 | static bool bc_num_strValid(const char *val, size_t base) | 2199 | static bool bc_num_strValid(const char *val, size_t base) |
2200 | { | 2200 | { |
2201 | BcDig b; | 2201 | BcDig b; |
2202 | bool small, radix = false; | 2202 | bool radix; |
2203 | size_t i, len = strlen(val); | ||
2204 | |||
2205 | if (!len) return true; | ||
2206 | |||
2207 | small = base <= 10; | ||
2208 | b = (BcDig)(small ? base + '0' : base - 10 + 'A'); | ||
2209 | |||
2210 | for (i = 0; i < len; ++i) { | ||
2211 | |||
2212 | BcDig c = val[i]; | ||
2213 | 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; | ||
2214 | if (c == '.') { | 2210 | if (c == '.') { |
2215 | |||
2216 | if (radix) return false; | 2211 | if (radix) return false; |
2217 | |||
2218 | radix = true; | 2212 | radix = true; |
2219 | continue; | 2213 | continue; |
2220 | } | 2214 | } |
2221 | 2215 | if (c < '0' || c >= b || (c > '9' && c < 'A')) | |
2222 | if (c < '0' || (small && c >= b) || (c > '9' && (c < 'A' || c >= b))) | ||
2223 | return false; | 2216 | return false; |
2224 | } | 2217 | } |
2225 | |||
2226 | return true; | 2218 | return true; |
2227 | } | 2219 | } |
2228 | 2220 | ||
2221 | // Note: n is already "bc_num_zero()"ed, | ||
2222 | // leading zeroes in "val" are removed | ||
2229 | static void bc_num_parseDecimal(BcNum *n, const char *val) | 2223 | static void bc_num_parseDecimal(BcNum *n, const char *val) |
2230 | { | 2224 | { |
2231 | size_t len, i; | 2225 | size_t len, i; |
2232 | const char *ptr; | 2226 | const char *ptr; |
2233 | bool zero = true; | 2227 | bool zero; |
2234 | 2228 | ||
2235 | for (i = 0; val[i] == '0'; ++i); | ||
2236 | |||
2237 | val += i; | ||
2238 | len = strlen(val); | 2229 | len = strlen(val); |
2239 | bc_num_zero(n); | 2230 | if (len == 0) |
2231 | return; | ||
2240 | 2232 | ||
2241 | if (len != 0) { | 2233 | zero = true; |
2242 | for (i = 0; zero && i < len; ++i) zero = val[i] == '0' || val[i] == '.'; | 2234 | for (i = 0; val[i]; ++i) { |
2243 | bc_num_expand(n, len); | 2235 | if (val[i] != '0' && val[i] != '.') { |
2236 | zero = false; | ||
2237 | break; | ||
2238 | } | ||
2244 | } | 2239 | } |
2240 | bc_num_expand(n, len); | ||
2245 | 2241 | ||
2246 | ptr = strchr(val, '.'); | 2242 | ptr = strchr(val, '.'); |
2247 | 2243 | ||
@@ -2255,26 +2251,29 @@ static void bc_num_parseDecimal(BcNum *n, const char *val) | |||
2255 | } | 2251 | } |
2256 | } | 2252 | } |
2257 | 2253 | ||
2254 | // Note: n is already "bc_num_zero()"ed, | ||
2255 | // leading zeroes in "val" are removed | ||
2258 | static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base) | 2256 | static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base) |
2259 | { | 2257 | { |
2260 | BcStatus s; | 2258 | BcStatus s; |
2261 | BcNum temp, mult, result; | 2259 | BcNum temp, mult, result; |
2262 | BcDig c = '\0'; | 2260 | BcDig c = '\0'; |
2263 | bool zero = true; | ||
2264 | unsigned long v; | 2261 | unsigned long v; |
2265 | size_t i, digits, len = strlen(val); | 2262 | size_t i, digits; |
2266 | 2263 | ||
2267 | bc_num_zero(n); | 2264 | for (i = 0; ; ++i) { |
2268 | 2265 | if (val[i] == '\0') | |
2269 | for (i = 0; zero && i < len; ++i) zero = (val[i] == '.' || val[i] == '0'); | 2266 | return; |
2270 | if (zero) return; | 2267 | if (val[i] != '.' && val[i] != '0') |
2268 | break; | ||
2269 | } | ||
2271 | 2270 | ||
2272 | bc_num_init_DEF_SIZE(&temp); | 2271 | bc_num_init_DEF_SIZE(&temp); |
2273 | bc_num_init_DEF_SIZE(&mult); | 2272 | bc_num_init_DEF_SIZE(&mult); |
2274 | 2273 | ||
2275 | for (i = 0; i < len; ++i) { | 2274 | for (;;) { |
2276 | 2275 | c = *val++; | |
2277 | c = val[i]; | 2276 | if (c == '\0') goto int_err; |
2278 | if (c == '.') break; | 2277 | if (c == '.') break; |
2279 | 2278 | ||
2280 | v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); | 2279 | v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); |
@@ -2286,19 +2285,15 @@ static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base) | |||
2286 | if (s) goto int_err; | 2285 | if (s) goto int_err; |
2287 | } | 2286 | } |
2288 | 2287 | ||
2289 | if (i == len) { | ||
2290 | c = val[i]; | ||
2291 | if (c == 0) goto int_err; | ||
2292 | } | ||
2293 | |||
2294 | bc_num_init(&result, base->len); | 2288 | bc_num_init(&result, base->len); |
2295 | //bc_num_zero(&result); - already is | 2289 | //bc_num_zero(&result); - already is |
2296 | bc_num_one(&mult); | 2290 | bc_num_one(&mult); |
2297 | 2291 | ||
2298 | for (i += 1, digits = 0; i < len; ++i, ++digits) { | 2292 | digits = 0; |
2299 | 2293 | for (;;) { | |
2300 | c = val[i]; | 2294 | c = *val++; |
2301 | if (c == 0) break; | 2295 | if (c == '\0') break; |
2296 | digits++; | ||
2302 | 2297 | ||
2303 | v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); | 2298 | v = (unsigned long) (c <= '9' ? c - '0' : c - 'A' + 10); |
2304 | 2299 | ||
@@ -2318,8 +2313,7 @@ static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base) | |||
2318 | 2313 | ||
2319 | if (n->len != 0) { | 2314 | if (n->len != 0) { |
2320 | if (n->rdx < digits) bc_num_extend(n, digits - n->rdx); | 2315 | if (n->rdx < digits) bc_num_extend(n, digits - n->rdx); |
2321 | } | 2316 | } else |
2322 | else | ||
2323 | bc_num_zero(n); | 2317 | bc_num_zero(n); |
2324 | 2318 | ||
2325 | err: | 2319 | err: |
@@ -2498,6 +2492,9 @@ static BcStatus bc_num_parse(BcNum *n, const char *val, BcNum *base, | |||
2498 | if (!bc_num_strValid(val, base_t)) | 2492 | if (!bc_num_strValid(val, base_t)) |
2499 | return bc_error("bad number string"); | 2493 | return bc_error("bad number string"); |
2500 | 2494 | ||
2495 | bc_num_zero(n); | ||
2496 | while (*val == '0') val++; | ||
2497 | |||
2501 | if (base_t == 10) | 2498 | if (base_t == 10) |
2502 | bc_num_parseDecimal(n, val); | 2499 | bc_num_parseDecimal(n, val); |
2503 | else | 2500 | else |
@@ -6387,7 +6384,7 @@ static BcStatus bc_program_asciify(void) | |||
6387 | { | 6384 | { |
6388 | BcStatus s; | 6385 | BcStatus s; |
6389 | BcResult *r, res; | 6386 | BcResult *r, res; |
6390 | BcNum *num = NULL, n; | 6387 | BcNum *num, n; |
6391 | char *str, *str2, c; | 6388 | char *str, *str2, c; |
6392 | size_t len = G.prog.strs.len, idx; | 6389 | size_t len = G.prog.strs.len, idx; |
6393 | unsigned long val; | 6390 | unsigned long val; |
@@ -6396,6 +6393,7 @@ static BcStatus bc_program_asciify(void) | |||
6396 | return bc_error_stack_has_too_few_elements(); | 6393 | return bc_error_stack_has_too_few_elements(); |
6397 | r = bc_vec_top(&G.prog.results); | 6394 | r = bc_vec_top(&G.prog.results); |
6398 | 6395 | ||
6396 | num = NULL; // TODO: is this NULL needed? | ||
6399 | s = bc_program_num(r, &num, false); | 6397 | s = bc_program_num(r, &num, false); |
6400 | if (s) return s; | 6398 | if (s) return s; |
6401 | 6399 | ||