aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--miscutils/bc.c88
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,
2199static bool bc_num_strValid(const char *val, size_t base) 2199static 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
2229static void bc_num_parseDecimal(BcNum *n, const char *val) 2223static 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
2258static void bc_num_parseBase(BcNum *n, const char *val, BcNum *base) 2256static 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
2325err: 2319err:
@@ -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