:: commit f0172ee1edaecb858ac347d5a80bbb8168f5a7fd

mintsuki <mintsuki@protonmail.com> — 2020-11-05 11:50

parents: 1ed9857231

blib: Make strtoui return the address of the first non-numeric digit

diff --git a/limine-pxe.bin b/limine-pxe.bin
index 8afef2a9..6846a495 100644
Binary files a/limine-pxe.bin and b/limine-pxe.bin differ
diff --git a/limine.bin b/limine.bin
index cb47f437..baf86a86 100644
Binary files a/limine.bin and b/limine.bin differ
diff --git a/stage2/lib/blib.c b/stage2/lib/blib.c
index 9ed4d9c4..dd4ea30f 100644
--- a/stage2/lib/blib.c
+++ b/stage2/lib/blib.c
@@ -66,14 +66,15 @@ int digit_to_int(char c) {
     return -1;
 }
 
-uint64_t strtoui(const char *s, size_t limit, int base) {
+uint64_t strtoui(const char *s, const char **end, int base) {
     uint64_t n = 0;
-    if (!limit)
-        limit = strlen(s);
-    for (size_t i = 0; i < limit; i++) {
+    for (size_t i = 0; ; i++) {
         int d = digit_to_int(s[i]);
-        if (d == -1)
+        if (d == -1) {
+            if (end != NULL)
+                *end = &s[i];
             break;
+        }
         n = n * base + d;
     }
     return n;
diff --git a/stage2/lib/blib.h b/stage2/lib/blib.h
index e177d0f2..b3c75ac2 100644
--- a/stage2/lib/blib.h
+++ b/stage2/lib/blib.h
@@ -16,7 +16,7 @@ __attribute__((noreturn)) void panic(const char *fmt, ...);
 
 int pit_sleep_and_quit_on_keypress(uint32_t pit_ticks);
 
-uint64_t strtoui(const char *s, size_t limit, int base);
+uint64_t strtoui(const char *s, const char **end, int base);
 
 #define DIV_ROUNDUP(a, b) (((a) + ((b) - 1)) / (b))
 
diff --git a/stage2/lib/libc.c b/stage2/lib/libc.c
index cb5844e4..56854437 100644
--- a/stage2/lib/libc.c
+++ b/stage2/lib/libc.c
@@ -72,21 +72,21 @@ size_t strlen(const char *str) {
 }
 
 int inet_pton(const char *src, void *dst) {
-    uint8_t array[4] = {};
+    uint8_t array[4];
     const char *current = src;
 
     for (int i = 0; i < 4; i++) {
-       long int value = strtoui(current, 0, 10);
-       if (value > 255)
-           return -1;
-       for (int j = 0; j < 3; j++) {
-           if (*current != '\0' && *current != '.')
-                current++;
-           else
-               break;
-       }
-       current++;
-       array[i] = value;
+        const char *newcur;
+        uint64_t value = strtoui(current, &newcur, 10);
+        if (current == newcur)
+            return -1;
+        current = newcur;
+        if (*current == 0 && i < 3)
+            return -1;
+        if (value > 255)
+            return -1;
+        current++;
+        array[i] = value;
     }
     memcpy(dst, array, 4);
     return 0;
diff --git a/stage2/lib/uri.c b/stage2/lib/uri.c
index bd83d867..c76885c7 100644
--- a/stage2/lib/uri.c
+++ b/stage2/lib/uri.c
@@ -51,6 +51,8 @@ bool uri_resolve(char *uri, char **resource, char **root, char **path) {
 // BIOS partitions are specified in the <BIOS drive>:<partition> form.
 // The drive may be omitted, the partition cannot.
 static bool parse_bios_partition(char *loc, uint8_t *drive, uint8_t *partition) {
+    uint64_t val;
+
     for (size_t i = 0; ; i++) {
         if (loc[i] == 0)
             return false;
@@ -60,10 +62,11 @@ static bool parse_bios_partition(char *loc, uint8_t *drive, uint8_t *partition)
             if (*loc == 0) {
                 *drive = boot_drive;
             } else {
-                if (strtoui(loc, 0, 10) < 1 || strtoui(loc, 0, 10) > 16) {
+                val = strtoui(loc, NULL, 10);
+                if (val < 1 || val > 16) {
                     panic("BIOS drive number outside range 1-16");
                 }
-                *drive = (strtoui(loc, 0, 10) - 1) + 0x80;
+                *drive = (val - 1) + 0x80;
             }
             loc += i + 1;
             break;
@@ -73,10 +76,11 @@ static bool parse_bios_partition(char *loc, uint8_t *drive, uint8_t *partition)
     if (*loc == 0)
         return false;
 
-    if (strtoui(loc, 0, 10) < 1 || strtoui(loc, 0, 10) > 256) {
+    val = strtoui(loc, NULL, 10);
+    if (val < 1 || val > 256) {
         panic("BIOS partition number outside range 1-256");
     }
-    *partition = strtoui(loc, 0, 10) - 1;
+    *partition = val - 1;
 
     return true;
 }
diff --git a/stage2/menu.c b/stage2/menu.c
index 90b14ab7..13ffcfaf 100644
--- a/stage2/menu.c
+++ b/stage2/menu.c
@@ -25,12 +25,12 @@ char *menu(void) {
 
     int selected_entry = 0;
     if (config_get_value(buf, 0, 16, "DEFAULT_ENTRY")) {
-        selected_entry = (int)strtoui(buf, 0, 10);
+        selected_entry = (int)strtoui(buf, NULL, 10);
     }
 
     int timeout = 5;
     if (config_get_value(buf, 0, 16, "TIMEOUT")) {
-        timeout = (int)strtoui(buf, 0, 10);
+        timeout = (int)strtoui(buf, NULL, 10);
     }
 
     if (!timeout)
@@ -53,43 +53,43 @@ char *menu(void) {
         };
 
         if (config_get_value(buf, 0, 16, "THEME_BLACK")) {
-            colourscheme[0] = (int)strtoui(buf, 0, 16);
+            colourscheme[0] = (int)strtoui(buf, NULL, 16);
         }
 
         if (config_get_value(buf, 0, 16, "THEME_RED")) {
-            colourscheme[1] = (int)strtoui(buf, 0, 16);
+            colourscheme[1] = (int)strtoui(buf, NULL, 16);
         }
 
         if (config_get_value(buf, 0, 16, "THEME_GREEN")) {
-            colourscheme[2] = (int)strtoui(buf, 0, 16);
+            colourscheme[2] = (int)strtoui(buf, NULL, 16);
         }
 
         if (config_get_value(buf, 0, 16, "THEME_BROWN")) {
-            colourscheme[3] = (int)strtoui(buf, 0, 16);
+            colourscheme[3] = (int)strtoui(buf, NULL, 16);
         }
 
         if (config_get_value(buf, 0, 16, "THEME_BLUE")) {
-            colourscheme[4] = (int)strtoui(buf, 0, 16);
+            colourscheme[4] = (int)strtoui(buf, NULL, 16);
         }
 
         if (config_get_value(buf, 0, 16, "THEME_MAGENTA")) {
-            colourscheme[5] = (int)strtoui(buf, 0, 16);
+            colourscheme[5] = (int)strtoui(buf, NULL, 16);
         }
 
         if (config_get_value(buf, 0, 16, "THEME_CYAN")) {
-            colourscheme[6] = (int)strtoui(buf, 0, 16);
+            colourscheme[6] = (int)strtoui(buf, NULL, 16);
         }
 
         if (config_get_value(buf, 0, 16, "THEME_GREY")) {
-            colourscheme[7] = (int)strtoui(buf, 0, 16);
+            colourscheme[7] = (int)strtoui(buf, NULL, 16);
         }
 
         if (config_get_value(buf, 0, 16, "THEME_MARGIN")) {
-            margin = (int)strtoui(buf, 0, 10);
+            margin = (int)strtoui(buf, NULL, 10);
         }
 
         if (config_get_value(buf, 0, 16, "THEME_MARGIN_GRADIENT")) {
-            margin_gradient = (int)strtoui(buf, 0, 10);
+            margin_gradient = (int)strtoui(buf, NULL, 10);
         }
 
         if (!config_get_value(cmdline, 0, CMDLINE_MAX, "BACKGROUND_PATH"))
diff --git a/stage2/protos/chainload.c b/stage2/protos/chainload.c
index d7a422bd..5281080f 100644
--- a/stage2/protos/chainload.c
+++ b/stage2/protos/chainload.c
@@ -47,15 +47,18 @@ static void spinup(uint8_t drive) {
 }
 
 void chainload(void) {
+    uint64_t val;
+
     int part; {
         char buf[32];
         if (!config_get_value(buf, 0, 32, "PARTITION")) {
             part = -1;
         } else {
-            if (strtoui(buf, 0, 10) < 1 || strtoui(buf, 0, 10) > 256) {
+            val = strtoui(buf, NULL, 10);
+            if (val < 1 || val > 256) {
                 panic("BIOS partition number outside range 1-256");
             }
-            part = (int)strtoui(buf, 0, 10);
+            part = val - 1;
         }
     }
     int drive; {
@@ -63,10 +66,11 @@ void chainload(void) {
         if (!config_get_value(buf, 0, 32, "DRIVE")) {
             panic("DRIVE not specified");
         }
-        if (strtoui(buf, 0, 10) < 1 || strtoui(buf, 0, 10) > 16) {
+        val = strtoui(buf, NULL, 10);
+        if (val < 1 || val > 16) {
             panic("BIOS drive number outside range 1-16");
         }
-        drive = (int)strtoui(buf, 0, 10);
+        drive = (val - 1) + 0x80;
     }
 
     term_deinit();
tab: 248 wrap: offon