From 6a0bc37a8ea85bb6bb7e50b3e886055531215070 Mon Sep 17 00:00:00 2001
From: VinceAle7082 <vinceale7082@gmail.com>
Date: Fri, 2 Aug 2024 19:28:04 +0200
Subject: [PATCH] Half implemented printf (doesn't compile)

---
 src/bootloader/stage2/stdio.c | 257 +++++++++++++++++++---------------
 1 file changed, 147 insertions(+), 110 deletions(-)

diff --git a/src/bootloader/stage2/stdio.c b/src/bootloader/stage2/stdio.c
index 13b54c5..6820e04 100644
--- a/src/bootloader/stage2/stdio.c
+++ b/src/bootloader/stage2/stdio.c
@@ -15,26 +15,29 @@ void puts(const char *str)
 }
 
 #define PRINTF_STATE_NORMAL         0
-#define PRINTF_STATE_LENGHT         1
-#define PRINTF_STATE_LENGHT_SHORT   2
-#define PRINTF_STATE_LENGHT_LONG    1
+#define PRINTF_STATE_LENGTH         1
+#define PRINTF_STATE_LENGTH_SHORT   2
+#define PRINTF_STATE_LENGTH_LONG    3
 #define PRINTF_STATE_SPEC           4
+
 #define PRINTF_LENGTH_DEFAULT       0
 #define PRINTF_LENGTH_SHORT_SHORT   1
 #define PRINTF_LENGTH_SHORT         2
 #define PRINTF_LENGTH_LONG          3
 #define PRINTF_LENGTH_LONG_LONG     4
-int* printf_number(int *argp, int length, bool sign, int radix)
-const char g_HexChars[] = '0123456789abcdef'
+
+int * printf_number(int *argp, int length, bool sign, int radix);
 
 void _cdecl printf(const char *fmt, ...)
 {
-    int *argp = (int*)&fmt;
+    int *argp = (int *)&fmt;
     int state = PRINTF_STATE_NORMAL;
     int length = PRINTF_LENGTH_DEFAULT;
     int radix = 10;
     bool sign = false;
+
     argp++;
+
     while (*fmt)
     {
         switch (state)
@@ -43,170 +46,204 @@ void _cdecl printf(const char *fmt, ...)
             switch (*fmt)
             {
             case '%':
-                state = PRINTF_STATE_LENGHT;
+                state = PRINTF_STATE_LENGTH;
                 break;
             default:
                 putc(*fmt);
                 break;
             }
-        
-        case PRINTF_STATE_LENGHT:
+            break;
+
+        case PRINTF_STATE_LENGTH:
             switch (*fmt)
             {
             case 'h':
                 length = PRINTF_LENGTH_SHORT;
-                state = PRINTF_STATE_LENGHT_SHORT;
+                state = PRINTF_STATE_LENGTH_SHORT;
                 break;
-            case 'l': 
+            case 'l':
                 length = PRINTF_LENGTH_LONG;
-                state = PRINTF_STATE_LENGHT_LONG;
+                state = PRINTF_STATE_LENGTH_LONG;
                 break;
-
             default:
-                goto PRINTF_STATE_SPEC;
+                goto PRINTF_STATE_SPEC_;
             }
             break;
 
-        case PRINTF_LENGTH_SHORT:
+        case PRINTF_STATE_LENGTH_SHORT:
             if (*fmt == 'h')
             {
                 length = PRINTF_LENGTH_SHORT_SHORT;
                 state = PRINTF_STATE_SPEC;
             }
             else
-            {
-                goto PRINTF_STATE_SPEC;
-            }
+                goto PRINTF_STATE_SPEC_;
             break;
-        
+
+        case PRINTF_STATE_LENGTH_LONG:
+            if (*fmt == 'l')
+            {
+                length = PRINTF_LENGTH_LONG_LONG;
+                state = PRINTF_STATE_SPEC;
+            }
+            else
+                goto PRINTF_STATE_SPEC_;
+            break;
+
         case PRINTF_STATE_SPEC:
+        PRINTF_STATE_SPEC_:
             switch (*fmt)
             {
-                case 'c':
-                    putc((char)*argp);
+            case 'c':
+                putc((char)*argp);
+                argp++;
+                break;
+
+            case 's':
+                if (length == PRINTF_LENGTH_LONG || length == PRINTF_LENGTH_LONG_LONG)
+                {
+                    puts_f(*(const char far **)argp);
+                    argp += 2;
+                }
+                else
+                {
+                    puts(*(const char **)argp);
                     argp++;
-                    break;
-                case 's': 
-                    puts(*(char **)argp);
-                    argp++;
-                    break;
-                case '%':
-                    putc('%');
-                    break;
-                case 'd': 
-                case 'i': 
-                    radix = 10;
-                    sign = true;
-                    argp = printf_number(argp, length, sign, radix);
-                    break;
-                case 'u':  
-                    radix = 10;
-                    sign = false;
-                    argp = printf_number(argp, length, sign, radix);
-                    break;
-                case 'x':
-                case 'X':
-                case 'p':
-                    radix = 16;
-                    sign = false;
-                    argp = printf_number(argp, length, sign, radix);
-                    break;
-                case 'o':
-                    radix = 8;
-                    sign = false;
-                    argp = printf_number(argp, length, sign, radix);
-                    break;
-                //Se รจ messo un carattere non valido questo codice fa in modo che li ignora.
-                default:
-                    break;
+                }
+                break;
+
+            case '%':
+                putc('%');
+                break;
+
+            case 'd':
+            case 'i':
+                radix = 10;
+                sign = true;
+                argp = printf_number(argp, length, sign, radix);
+                break;
+
+            case 'u':
+                radix = 10;
+                sign = false;
+                argp = printf_number(argp, length, sign, radix);
+                break;
+
+            case 'X':
+            case 'x':
+            case 'p':
+                radix = 16;
+                sign = false;
+                argp = printf_number(argp, length, sign, radix);
+                break;
+
+            case 'o':
+                radix = 8;
+                sign = false;
+                argp = printf_number(argp, length, sign, radix);
+                break;
+
+            // ignore invalid spec
+            default:
+                break;
             }
-            //Porta le variabili allo stato di default / normale.
+
+            // reset state
             state = PRINTF_STATE_NORMAL;
             length = PRINTF_LENGTH_DEFAULT;
             radix = 10;
             sign = false;
             break;
         }
+
         fmt++;
     }
 }
 
-int* printf_number(int* argp, int length, bool sign, int radix)
+const char g_HexChars[] = "0123456789abcdef";
+
+int *printf_number(int *argp, int length, bool sign, int radix)
 {
     char buffer[32];
     unsigned long long number;
     int number_sign = 1;
     int pos = 0;
 
+    // process length
     switch (length)
     {
-        case PRINTF_LENGTH_SHORT_SHORT:
-        case PRINTF_LENGTH_SHORT:
-        case PRINTF_LENGTH_LONG:
-            if (sign)
+    case PRINTF_LENGTH_SHORT_SHORT:
+    case PRINTF_LENGTH_SHORT:
+    case PRINTF_LENGTH_DEFAULT:
+        if (sign)
+        {
+            int n = *argp;
+            if (n < 0)
             {
-                long int n = *(long int*)argp;
-                if (n < 0)
-                {
-                    n = -n;
-                    number_sign = -1;
-                }
-                number = (unsigned long long)n;
+                n = -n;
+                number_sign = -1;
             }
-            else
-            {
-                number = (*unsigned long int*)argp;
-            }
-            argp += 2;
-            break;
-        case PRINTF_LENGTH_LONG_LONG:
-            if (sign)
-            {
-                long long int n = *(long long int*)argp;
-                if (n < 0)
-                {
-                    n = -n;
-                    number_sign = -1;
-                }
-                number = (unsigned long long)n;
-            }
-            else
-            {
-                number = (*unsigned long long int *)argp;
-            }
-            argp += 4;
-            break;
-        case PRINTF_LENGTH_DEFAULT:
-            if (sign)
-            {
-                int n = *argp;
-                if (n < 0)
-                {
-                    n = -n;
-                    number_sign = -1;
-                }
-                number = n;
-            }
-            else
-            {
-                number = (*unsigned int*)argp;
+            number = (unsigned long long)n;
+        }
+        else
+        {
+            number = *(unsigned int *)argp;
+        }
+        argp++;
+        break;
 
+    case PRINTF_LENGTH_LONG:
+        if (sign)
+        {
+            long int n = *(long int *)argp;
+            if (n < 0)
+            {
+                n = -n;
+                number_sign = -1;
             }
-            argp++;
-            break;
+            number = (unsigned long long)n;
+        }
+        else
+        {
+            number = *(unsigned long int *)argp;
+        }
+        argp += 2;
+        break;
+
+    case PRINTF_LENGTH_LONG_LONG:
+        if (sign)
+        {
+            long long int n = *(long long int *)argp;
+            if (n < 0)
+            {
+                n = -n;
+                number_sign = -1;
+            }
+            number = (unsigned long long)n;
+        }
+        else
+        {
+            number = *(unsigned long long int *)argp;
+        }
+        argp += 4;
+        break;
     }
+
+    // convert number to ASCII
     do
     {
-        uint32_t rem = number % radix;
+        uint32_t rem;
+        x86_div64_32(number, radix, &number, &rem);
         buffer[pos++] = g_HexChars[rem];
     } while (number > 0);
 
+    // add sign
     if (sign && number_sign < 0)
-    {
         buffer[pos++] = '-';
-    }
 
+    // print number in reverse order
     while (--pos >= 0)
         putc(buffer[pos]);
+
     return argp;
 }
\ No newline at end of file