Kaynağa Gözat

Give expected results for negative non-base-10 numbers in tonumber().

This was undefined in Lua 5.1, but it's defined in 5.2.
Mike Pall 7 yıl önce
ebeveyn
işleme
f3cf0d6e15
1 değiştirilmiş dosya ile 18 ekleme ve 9 silme
  1. 18 9
      src/lib_base.c

+ 18 - 9
src/lib_base.c

@@ -287,18 +287,27 @@ LJLIB_ASM(tonumber)		LJLIB_REC(.)
   } else {
   } else {
     const char *p = strdata(lj_lib_checkstr(L, 1));
     const char *p = strdata(lj_lib_checkstr(L, 1));
     char *ep;
     char *ep;
+    unsigned int neg = 0;
     unsigned long ul;
     unsigned long ul;
     if (base < 2 || base > 36)
     if (base < 2 || base > 36)
       lj_err_arg(L, 2, LJ_ERR_BASERNG);
       lj_err_arg(L, 2, LJ_ERR_BASERNG);
-    ul = strtoul(p, &ep, base);
-    if (p != ep) {
-      while (lj_char_isspace((unsigned char)(*ep))) ep++;
-      if (*ep == '\0') {
-	if (LJ_DUALNUM && LJ_LIKELY(ul < 0x80000000u))
-	  setintV(L->base-1-LJ_FR2, (int32_t)ul);
-	else
-	  setnumV(L->base-1-LJ_FR2, (lua_Number)ul);
-	return FFH_RES(1);
+    while (lj_char_isspace((unsigned char)(*p))) p++;
+    if (*p == '-') { p++; neg = 1; } else if (*p == '+') { p++; }
+    if (lj_char_isalnum((unsigned char)(*p))) {
+      ul = strtoul(p, &ep, base);
+      if (p != ep) {
+	while (lj_char_isspace((unsigned char)(*ep))) ep++;
+	if (*ep == '\0') {
+	  if (LJ_DUALNUM && LJ_LIKELY(ul < 0x80000000u+neg)) {
+	    if (neg) ul = -ul;
+	    setintV(L->base-1-LJ_FR2, (int32_t)ul);
+	  } else {
+	    lua_Number n = (lua_Number)ul;
+	    if (neg) n = -n;
+	    setnumV(L->base-1-LJ_FR2, n);
+	  }
+	  return FFH_RES(1);
+	}
       }
       }
     }
     }
   }
   }