*********
As I was typing this and I was about to post this, I was doing `undo` in my editor to go back to the original code (the one I'm posting). However, I missed one `undo` and I run the program again and for my big surprise.... IT WORKED! Well the last one was the one making <end> a signed variable from an unsigned one. It turns out that the problem was that in the codition, because we were trying to check values of different signs. I don't know what the compiler does under the hood but changing <end> from "u64" to "i64" fixed the program. Again, one more example of unsigned values causing problems...

I want to hear your thougts one that one! I'm making a compiler and I'm thinking of not supporting unsigned values. I prefer supporting 128-bits using two registers to cover any range needs. As you can see, unsigned variables can leed to very sneaky bugs. I was literally trying to fix this for more than half an hour. Half an hour for something so small.... I know that they have caused more serious problems to more experianced and proffesional developres than me too! My language will focus on safetly and on trying to help the user on avoding doing mistakes and spend hours debugging so allowing and banning unsigned variables is very crucial! Thanks for reading!
*********

ORIGINAL POST:
It's late here so maybe I'm blind. If not, then I tried so much to find what I'm doing wrong but I wasn't able to find it. So, I have the following code snippet:

Code:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"

typedef unsigned long  u64;
typedef long           i64;

u64 get_final_num(const char*  value, i64 slen) {
  u64 end = 0;

  u64 final_val = 0;
  u64 multi = 1;

  // NOTE: Another case when the oveflow caused me problems. Should I remove unsigned values????
  printf("slen = %lu, end = %lu\n", slen, end);
  int i = 0;
  while (--slen >= end) {
    printf("slen: %ld, end: %lu, value: %d\n", slen, end, value[slen]);
    i++;
    // printf("\nslen: %lu\n", slen);
    if (value[slen] >= 48 && value[slen] <= 57) {
      final_val += (value[slen] - 48) * multi;
      multi *= 10;
    }

    else { printf("HITS HERE!!! after loop: %d, slen: %ld\n", i, slen); return 2; } // Error, the character is not a digit
  }

  return final_val;
}

u64 str_to_u64(const char* value) {
  i64 slen = strlen(value);

  // Error, the value is an empty string
  if (strcmp(value, "") == 0) { return 0; }

  if (slen == 1) {
    if (*value == '-') { return 1; } // Error, there is no number after '-'

    else { return get_final_num(value, slen); }
  }

  return get_final_num(value, slen);
}

int main() {
  char* s1 = "12345678910";
  printf("libc: %ld | mylib: %ld\n", strtol(s1, NULL, 10), str_to_u64(s1));
  return 0;
}
The big thing her is the "while" loop. So the condition says: "keep looping as long as <slen> is bigger or equal to <end>" and first, it decrements <slen>. Now, the `printf` in the else branch will tell something interesting. When the code hits this branch, <slen> will have the value "-1" which is bigger than the value of <end> which is 0. So why did the condition executed???

If I change the code slightly by making <end> a signed varibale and set its value to to 1 and change the condition to "while(--slen > end)" then the program seems to work as expected.

Again, sorry if I'm blind and I can't see something obvious. I could just leave it as it is and move on as I find the alternative way that it works but I what to find what I'm doing wrong. I really did tried to check it multiple times but I cannot seem to find what it is....