ref: 40b1fef01b2962896ed4eab1ae7f90eb7f58a73f
parent: 3ffef0f58e132850684dad253b11ba73cfa959c1
author: Mahdi <mahdi.hoseini1381@yahoo.com>
date: Thu Nov 23 07:31:01 EST 2023
Added printf.c, scanf.c, strtol.c, strncpy.c, itoa.c
--- /dev/null
+++ b/libc/itoa.c
@@ -1,0 +1,39 @@
+char*
+itoa( int value, int base )
+{
+ char *rc;
+ char *ptr;
+ char *low;
+ char *str;
+ // Check for supported base.
+ if ( base < 2 || base > 36 )
+ {
+ *str = '\0';
+ return str;
+ }
+ rc = ptr = str;
+ // Set '-' for negative decimals.
+ if ( value < 0 && base == 10 )
+ {
+ *ptr++ = '-';
+ }
+ // Remember where the numbers start.
+ low = ptr;
+ // The actual conversion.
+ do
+ {
+ // Modulo is negative for negative value. This trick makes abs() unnecessary.
+ *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + value % base];
+ value /= base;
+ } while ( value );
+ // Terminating the string.
+ *ptr-- = '\0';
+ // Invert the numbers.
+ while ( low < ptr )
+ {
+ char tmp = *low;
+ *low++ = *ptr;
+ *ptr-- = tmp;
+ }
+ return rc;
+}
\ No newline at end of file
--- /dev/null
+++ b/libc/printf.c
@@ -1,0 +1,86 @@
+#include <u.h>
+#include <libc.h>
+
+int
+print_char(int c)
+{
+ return vga_putc(c);
+}
+
+int
+print_str(char *str)
+{
+
+ vga_puts(str);
+
+ return strlen(str);
+}
+
+int
+print_digit(long num, int base)
+{
+ int count;
+ char* symbols = "0123456789abcdef";
+
+ if (num < 0)
+ {
+ vga_puts("-");
+ return print_digit(-num, base) + 1;
+ }
+ else if (num < base)
+ {
+ return print_char(symbols[num]);
+ }
+ else
+ {
+ count = print_digit(num / base, base);
+ return count + print_digit(num % base, base);
+ }
+
+}
+
+int
+print_format(char specifier, va_list ap)
+{
+ int count = 0;
+
+ switch (specifier)
+ {
+ case 'c':
+ count += print_char(va_arg(ap, int)); // Type promotion
+ break;
+ case 's':
+ count += print_str(va_arg(ap, char*));
+ break;
+ case 'd':
+ count += print_digit((long)va_arg(ap, int), 10);
+ break;
+ case 'x':
+ count += print_digit((long)va_arg(ap, unsigned int), 16);
+ default:
+ count += vga_puts(specifier);
+ break;
+ }
+
+ return count;
+}
+
+int
+printf(const char* restrict format, ...)
+{
+ va_list ap;
+ va_start(ap, format);
+ int count = 0;
+
+ while (*format)
+ {
+ if (*format == '%')
+ count += print_format(*(++format), ap);
+ else
+ count += vga_putc(format);
+ format++;
+ }
+
+ va_end(ap);
+ return count;
+}
--- /dev/null
+++ b/libc/scanf.c
@@ -1,0 +1,58 @@
+
+#include <u.h>
+#include <libc.h>
+
+int scanf (char * str, ...)
+{
+ va_list vl;
+ int i = 0, j=0, ret = 0;
+ char buff[100] = {0}, tmp[20], c;
+ char *out_loc;
+ while(c != '\0')
+ {
+ c = ps2_getc();
+ buff[i] = c;
+ i++;
+ }
+ va_start( vl, str );
+ i = 0;
+ while (str && str[i])
+ {
+ if (str[i] == '%')
+ {
+ i++;
+ switch (str[i])
+ {
+ case 'c':
+ {
+ *(char *)va_arg( vl, char* ) = buff[j];
+ j++;
+ ret ++;
+ break;
+ }
+ case 'd':
+ {
+ *(int *)va_arg( vl, int* ) =strtol(&buff[j], &out_loc, 10);
+ j+=out_loc -&buff[j];
+ ret++;
+ break;
+ }
+ case 'x':
+ {
+ *(int *)va_arg( vl, int* ) =strtol(&buff[j], &out_loc, 16);
+ j+=out_loc -&buff[j];
+ ret++;
+ break;
+ }
+ }
+ }
+ else
+ {
+ buff[j] =str[i];
+ j++;
+ }
+ i++;
+ }
+ va_end(vl);
+ return ret;
+}
--- /dev/null
+++ b/libc/strncpy.c
@@ -1,0 +1,20 @@
+#include <u.h>
+
+char*
+strncpy(char *dst, const char *src, size_t num)
+{
+ char *dst_p = dst;
+
+ if (num != 0) {
+
+ do {
+ if ((*dst++ = *src++) == 0) {
+ /* NULL pad the remaining n-1 bytes */
+ while (--num != 0)
+ *dst++ = 0;
+ break;
+ }
+ } while (--num != 0);
+ }
+ return (dst_p);
+}
--- /dev/null
+++ b/libc/strtol.c
@@ -1,0 +1,97 @@
+#include <u.h>
+
+long
+strtol(char *nptr, char **endptr, int base)
+{
+ char *p;
+ long n, nn, m;
+ int c, ovfl, v, neg, ndig;
+
+ p = nptr;
+ neg = 0;
+ n = 0;
+ ndig = 0;
+ ovfl = 0;
+
+ /*
+ * White space
+ */
+ for(;; p++) {
+ switch(*p) {
+ case ' ':
+ case '\t':
+ case '\n':
+ case '\f':
+ case '\r':
+ case '\v':
+ continue;
+ }
+ break;
+ }
+
+ /*
+ * Sign
+ */
+ if(*p=='-' || *p=='+')
+ if(*p++ == '-')
+ neg = 1;
+
+ /*
+ * Base
+ */
+ if(base==0) {
+ base = 10;
+ if(*p == '0') {
+ base = 8;
+ if(p[1]=='x' || p[1]=='X') {
+ p += 2;
+ base = 16;
+ }
+ }
+ } else
+ if(base==16 && *p=='0'){
+ if(p[1]=='x' || p[1]=='X')
+ p += 2;
+ } else
+ if(base<0 || 36<base)
+ goto Return;
+
+ /*
+ * Non-empty sequence of digits
+ */
+ m = LONG_MAX/base;
+ for(;; p++,ndig++){
+ c = *p;
+ v = base;
+ if('0'<=c && c<='9')
+ v = c - '0';
+ else
+ if('a'<=c && c<='z')
+ v = c - 'a' + 10;
+ else
+ if('A'<=c && c<='Z')
+ v = c - 'A' + 10;
+ if(v >= base)
+ break;
+ if(n > m)
+ ovfl = 1;
+ nn = n*base + v;
+ if(nn < n)
+ ovfl = 1;
+ n = nn;
+ }
+
+Return:
+ if(ndig == 0)
+ p = nptr;
+ if(endptr)
+ *endptr = p;
+ if(ovfl){
+ if(neg)
+ return LONG_MIN;
+ return LONG_MAX;
+ }
+ if(neg)
+ return -n;
+ return n;
+}