From 9434506035c3fc01de55ac0bc8b75497f8b5df5f Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 27 Mar 2014 12:33:32 +0900 Subject: allow underscores in integer literals; close #1960 --- src/string.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) (limited to 'src/string.c') diff --git a/src/string.c b/src/string.c index 266db4989..0bee35d0e 100644 --- a/src/string.c +++ b/src/string.c @@ -1952,10 +1952,10 @@ mrb_str_split_m(mrb_state *mrb, mrb_value str) mrb_value mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck) { - char *end; + const char *p; char sign = 1; - int c; - unsigned long n; + int c, us; + unsigned long n = 0; mrb_int val; #undef ISDIGIT @@ -2042,7 +2042,7 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck) break; } /* end of switch (base) { */ if (*str == '0') { /* squeeze preceeding 0s */ - int us = 0; + us = 0; while ((c = *++str) == '0' || c == '_') { if (c == '_') { if (++us >= 2) @@ -2060,15 +2060,32 @@ mrb_cstr_to_inum(mrb_state *mrb, const char *str, int base, int badcheck) return mrb_fixnum_value(0); } - n = strtoul((char*)str, &end, base); + us = 0; + for (p=str;*p;p++) { + if (*p == '_') { + if (us == 0) { + us++; + continue; + } + if (badcheck) goto bad; + break; + } + c = conv_digit(*p); + if (c < 0 || c >= base) { + if (badcheck) goto bad; + break; + } + n *= base; + n += c; + } if (n > MRB_INT_MAX) { mrb_raisef(mrb, E_ARGUMENT_ERROR, "string (%S) too big for integer", mrb_str_new_cstr(mrb, str)); } val = n; if (badcheck) { - if (end == str) goto bad; /* no number */ - while (*end && ISSPACE(*end)) end++; - if (*end) goto bad; /* trailing garbage */ + if (p == str) goto bad; /* no number */ + while (*p && ISSPACE(*p)) p++; + if (*p) goto bad; /* trailing garbage */ } return mrb_fixnum_value(sign ? val : -val); -- cgit v1.2.3