aboutsummaryrefslogtreecommitdiff
path: root/libpsn00b/libc
diff options
context:
space:
mode:
authorJohn Wilbert M. Villamor <lameguy64@gmail.com>2019-07-17 11:30:07 +0800
committerJohn Wilbert M. Villamor <lameguy64@gmail.com>2019-07-17 11:30:07 +0800
commit0d4345a9bf2623df079c50a3bc73cbb7deca1176 (patch)
tree6cda70b844f39fc2d65a806b91a6010066433b56 /libpsn00b/libc
parentb956c5391b955e793a4d54572aa58872b4c66c30 (diff)
downloadpsn00bsdk-0d4345a9bf2623df079c50a3bc73cbb7deca1176.tar.gz
Added C++ support, updated build instructions and makefiles, consolidated libc and libgcc (during build process), libraries now v0.12b and more
Diffstat (limited to 'libpsn00b/libc')
-rw-r--r--libpsn00b/libc/_mem_init.s20
-rw-r--r--libpsn00b/libc/abort.c9
-rw-r--r--libpsn00b/libc/c++-support.cxx40
-rw-r--r--libpsn00b/libc/makefile23
-rw-r--r--libpsn00b/libc/start.c57
-rw-r--r--libpsn00b/libc/start.s39
-rw-r--r--libpsn00b/libc/vsprintf.c788
-rw-r--r--libpsn00b/libc/vsprintf.c-old (renamed from libpsn00b/libc/printf.c)8
8 files changed, 932 insertions, 52 deletions
diff --git a/libpsn00b/libc/_mem_init.s b/libpsn00b/libc/_mem_init.s
new file mode 100644
index 0000000..672ac2f
--- /dev/null
+++ b/libpsn00b/libc/_mem_init.s
@@ -0,0 +1,20 @@
+.set noreorder
+
+.global _mem_init
+.type _mem_init, @function
+_mem_init:
+
+.section .text
+
+_mem_init:
+ la $a0, __bss_start
+ la $a1, _end
+.Lclear_bss:
+ sb $0 , 0($a0)
+ blt $a0, $a1, .Lclear_bss
+ addiu $a0, 1
+ la $a0, _end+4 # Initialize heap for malloc (does not use BIOS maalloc)
+ li $a1, 1572864 # Allocate 1.5MB at end of bss
+ j InitHeap
+ nop
+ \ No newline at end of file
diff --git a/libpsn00b/libc/abort.c b/libpsn00b/libc/abort.c
new file mode 100644
index 0000000..ca5ab1d
--- /dev/null
+++ b/libpsn00b/libc/abort.c
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+void abort() {
+
+ printf("abort()\n");
+
+ while(1);
+
+} \ No newline at end of file
diff --git a/libpsn00b/libc/c++-support.cxx b/libpsn00b/libc/c++-support.cxx
new file mode 100644
index 0000000..fcf7cfc
--- /dev/null
+++ b/libpsn00b/libc/c++-support.cxx
@@ -0,0 +1,40 @@
+#include <assert.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <malloc.h>
+
+extern "C"
+
+void __cxa_pure_virtual(void) {
+ /* Pure C++ virtual call; abort! */
+ assert(false);
+}
+
+void* operator new(size_t size) {
+ return malloc(size);
+}
+
+void* operator new[](size_t size) {
+ return malloc(size);
+}
+
+void operator delete(void* ptr) {
+ free(ptr);
+}
+
+void operator delete[](void* ptr) {
+ free(ptr);
+}
+
+/*-
+ * <https://en.cppreference.com/w/cpp/memory/new/operator_delete>
+ *
+ * Called if a user-defined replacement is provided, except that it's
+ * unspecified whether other overloads or this overload is called when deleting
+ * objects of incomplete type and arrays of non-class and trivially-destructible
+ * class types.
+ *
+ * A memory allocator can use the given size to be more efficient */
+void operator delete(void* ptr, unsigned int) {
+ free(ptr);
+} \ No newline at end of file
diff --git a/libpsn00b/libc/makefile b/libpsn00b/libc/makefile
index feadbdb..67f2284 100644
--- a/libpsn00b/libc/makefile
+++ b/libpsn00b/libc/makefile
@@ -2,20 +2,20 @@
# Part of the PSn00bSDK Project
# 2019 Lameguy64 / Meido-Tek Productions
-PREFIX = mipsel-unknown-elf-
+include ../common.mk
TARGET = ../libc.a
-CFILES = $(notdir $(wildcard ./*.c))
-AFILES = $(notdir $(wildcard ./*.s))
-OFILES = $(addprefix build/,$(CFILES:.c=.o) $(AFILES:.s=.o))
+CFILES = $(notdir $(wildcard ./*.c))
+CXXFILES = $(notdir $(wildcard ./*.cxx))
+AFILES = $(notdir $(wildcard ./*.s))
+OFILES = $(addprefix build/,$(CFILES:.c=.o) $(CXXFILES:.cxx=.o) $(AFILES:.s=.o))
-INCLUDE = -I../include
-
-CFLAGS = -O2 -msoft-float -fno-builtin -fdata-sections -ffunction-sections -Wa,--strip-local-absolute
-AFLAGS = -msoft-float -Wa,--strip-local-absolute
+CFLAGS = -g -O2 -msoft-float -fno-builtin -fdata-sections -ffunction-sections -Wa,--strip-local-absolute
+AFLAGS = -g -msoft-float -Wa,--strip-local-absolute
CC = $(PREFIX)gcc
+CXX = $(PREFIX)g++
AS = $(PREFIX)as
AR = $(PREFIX)ar
RANLIB = $(PREFIX)ranlib
@@ -23,12 +23,17 @@ RANLIB = $(PREFIX)ranlib
all: $(TARGET)
$(TARGET): $(OFILES)
- $(AR) cr $(TARGET) $(OFILES)
+ cp $(GCC_BASE)/lib/gcc/mipsel-unknown-elf/$(GCC_VERSION)/libgcc.a ./$(TARGET)
+ $(AR) r $(TARGET) $(OFILES)
$(RANLIB) $(TARGET)
build/%.o: %.c
@mkdir -p $(dir $@)
$(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
+
+build/%.o: %.cxx
+ @mkdir -p $(dir $@)
+ $(CXX) $(CFLAGS) $(INCLUDE) -c $< -o $@
build/%.o: %.s
@mkdir -p $(dir $@)
diff --git a/libpsn00b/libc/start.c b/libpsn00b/libc/start.c
new file mode 100644
index 0000000..c234e03
--- /dev/null
+++ b/libpsn00b/libc/start.c
@@ -0,0 +1,57 @@
+#include <stdio.h>
+#include <malloc.h>
+
+#define load_gp() __asm__ volatile ( \
+ "la $gp, _gp;" )
+
+extern int _end;
+extern int main(int argc, const char* argv[]);
+
+void _mem_init(void);
+
+
+static void _call_global_ctors(void)
+{
+ extern void (*__CTOR_LIST__[])(void);
+
+ // Constructors are called in reverse order of the list
+ int i;
+ for (i = (int)__CTOR_LIST__[0]; i >= 1; i--) {
+ // Each function handles one or more destructor (within
+ // file scope)
+ __CTOR_LIST__[i]();
+ }
+}
+
+static void _call_global_dtors(void)
+{
+ extern void (*__DTOR_LIST__[])(void);
+
+ /* Destructors in forward order */
+ int i;
+ for (i = 0; i < (int)__DTOR_LIST__[0]; i++) {
+ /* Each function handles one or more destructor (within
+ * file scope) */
+ __DTOR_LIST__[i + 1]();
+ }
+}
+
+void _start(void) {
+
+ // Load GP address
+ load_gp();
+
+ // Mem init assembly function (clears BSS and InitHeap to _end which is
+ // not possible to do purely in C because the linker complains about
+ // relocation truncated to fit: R_MIPS_GPREL16 against `_end'
+ // Workaround is to do it in assembly because la pseudo-op doesn't use
+ // stupid gp relative addressing
+ _mem_init();
+
+ _call_global_ctors();
+
+ main(0, NULL);
+
+ _call_global_dtors();
+
+} \ No newline at end of file
diff --git a/libpsn00b/libc/start.s b/libpsn00b/libc/start.s
deleted file mode 100644
index 2cf6ed0..0000000
--- a/libpsn00b/libc/start.s
+++ /dev/null
@@ -1,39 +0,0 @@
-# Start function!
-# This is essentially the entry point of the PS-EXE
-
-.set noreorder
-
-.section .text
-
-.global _start
-.type _start, @function
-_start:
- addiu $sp, -4
- sw $ra, 0($sp)
-
- la $gp, _gp # Very important!
-
- la $a0, .bss # What are the CORRECT symbols for BSS start and end?
- la $a1, _end
-.Lclear_bss:
- sb $0 , 0($a0)
- blt $a0, $a1, .Lclear_bss
- addiu $a0, 1
-
- la $a0, _end+4 # Initialize heap for malloc (does not use BIOS maalloc)
- li $a1, 1572864
- jal InitHeap
- nop
-
- move $a0, $0 # No support for arguments for now
- move $a1, $0
-
- jal main
- addiu $sp, -8
- addiu $sp, 8
-
- lw $ra, 0($sp) # Return
- addiu $sp, 4
- jr $ra
- nop
- \ No newline at end of file
diff --git a/libpsn00b/libc/vsprintf.c b/libpsn00b/libc/vsprintf.c
new file mode 100644
index 0000000..153ca21
--- /dev/null
+++ b/libpsn00b/libc/vsprintf.c
@@ -0,0 +1,788 @@
+/* printf.c
+ *
+ * Inherited from the PSXSDK C library
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define SPRINTF_ALT_FLAG (1<<0)
+#define SPRINTF_ZERO_FLAG (1<<1)
+#define SPRINTF_NEGFIELD_FLAG (1<<2)
+#define SPRINTF_SPACE_FLAG (1<<3)
+#define SPRINTF_SIGN_FLAG (1<<4)
+
+// sprintf() macros to calculate the real padding and to write it
+// these were made to not repeat the code in the function
+// they can only be used in sprintf()
+
+// sprintf macros START
+
+#define calculate_real_padding() \
+ y = 1; \
+ \
+ for(x=0;x<=19;x++) \
+ { \
+ if(x == 0) \
+ pad_quantity--; \
+ else \
+ { \
+ if(arg / y) \
+ pad_quantity--; \
+ } \
+ \
+ y *= 10; \
+ } \
+ \
+ if(pad_quantity < 0) pad_quantity = 0;
+
+/*#define calculate_real_padding_hex() \
+ for (x = 0; x < 8; x++) \
+ { \
+ if(x == 0) \
+ pad_quantity--; \
+ else \
+ { \
+ if((arg >> (x * 4)) & 0xf) \
+ pad_quantity--; \
+ } \
+ }*/
+
+#define calculate_real_padding_hex() \
+ last = 0; \
+ for (x = 0; x < 16; x++) \
+ if((arg >> (x * 4)) & 0xf) \
+ last = x; \
+ \
+ pad_quantity = (pad_quantity - 1) - last; \
+ if(pad_quantity < 0) pad_quantity = 0;
+
+#define write_padding() \
+ if(!(flags & SPRINTF_NEGFIELD_FLAG)) \
+ for(x = 0; x < pad_quantity; x++) \
+ { \
+ if(flags & SPRINTF_ZERO_FLAG) \
+ put_in_string(string, ssz, '0', string_pos++); \
+ else \
+ put_in_string(string, ssz, ' ', string_pos++); \
+ }
+
+#define write_neg_padding() \
+ if(flags & SPRINTF_NEGFIELD_FLAG) \
+ { \
+ for(x = 0; x < pad_quantity; x++) \
+ put_in_string(string, ssz, ' ', string_pos++);\
+ }
+
+// sprintf macros END
+
+enum
+{
+ SPRINTF_SIZE_CHAR,
+ SPRINTF_SIZE_SHORT,
+ SPRINTF_SIZE_INT,
+ SPRINTF_SIZE_LONG,
+ SPRINTF_SIZE_LONG_LONG,
+};
+
+unsigned int get_arg_in_size(int size, unsigned long *arg, unsigned int check_sign)
+{
+ int s = 0;
+
+ switch(size)
+ {
+ case SPRINTF_SIZE_CHAR:
+ *arg &= 0xff;
+
+ if(check_sign)
+ {
+ if(*arg & (1<<7))
+ {
+ *arg |= 0xffffff00;
+ *arg = ~(*arg - 1);
+ s = 1;
+ }
+ }
+ break;
+ case SPRINTF_SIZE_SHORT:
+ *arg &= 0xffff;
+
+ if(check_sign)
+ {
+ if(*arg & (1<<15))
+ {
+ *arg |= 0xffff0000;
+ *arg = ~(*arg - 1);
+ s = 1;
+ }
+ }
+ break;
+
+// sizeof(long) == sizeof(int) on 32bit, so this will suffice for the psx
+
+ case SPRINTF_SIZE_INT:
+ case SPRINTF_SIZE_LONG:
+ *arg &= 0xffffffff;
+
+ /*if(check_sign)
+ {
+ if(*arg & (1<<31))
+ {
+ *arg |= (long long)0xffffffff00000000;
+ *arg = ~(*arg - 1);
+ s = 1;
+ }
+ }*/
+ break;
+
+ /*case SPRINTF_SIZE_LONG_LONG:
+ if(check_sign)
+ {
+ if(*arg & ((long long)1<<63))
+ {
+ *arg = ~(*arg - 1);
+ s = 1;
+ }
+ }
+ break;*/
+ }
+
+ return s;
+}
+
+int put_in_string(char *string, unsigned int sz, char c, int pos)
+{
+ if(pos>=sz)
+ return 0;
+ else
+ string[pos] = c;
+
+ return 1;
+}
+
+int libc_ulltoa(unsigned long i, char *dst, int n)
+{
+ int x, y;
+ unsigned long a, b;
+ int empty_digit = 1;
+ int sp=0;
+ int n2=0;
+
+ for(x=20;x>=0;x--)
+ {
+ a = 1;
+ for(y = 0; y<x; y++)
+ a *= 10;
+
+ b = (i/a);
+
+ if(b>=1)
+ empty_digit = 0;
+
+ if(empty_digit == 0 || x == 0)
+ {
+ i -= b*a;
+
+ //put_in_string(string, ssz, b + '0', string_pos++);
+ if(n2!=n)
+ {
+ //printf("n2=%d\n",n2);
+ dst[sp++] = b + '0';
+ n2++;
+ }
+ }
+ }
+
+ if(n2!=n)dst[sp] = 0;
+
+ return n2;
+}
+
+void libc_float_to_string(float fl, char *dst, int n)
+{
+ unsigned int *p = (unsigned int*)&fl;
+ unsigned long long i = 0;
+ unsigned long long f = 0;
+ int e, m, s;
+ int x, y;
+ unsigned long long z;
+
+ s = *p >> 31;
+
+ e = (*p >> 23) & 0xff;
+
+ m = *p & 0x7fffff;
+
+ if(e == 255 && m == 0) // Infinity
+ {
+ if(s) strncpy(dst, "-inf", n);
+ else strncpy(dst, "inf", n);
+ }else if(e == 255 && m != 0) // NaN
+ {
+ strncpy(dst, "nan", n);
+ }
+ else
+ {
+ e -= 127;
+ m |= 1<<23;
+
+
+
+ for(x = 23; x >= 0; x--)
+ {
+ if(m & (1<<x))
+ {
+ if(e >= 0)
+ {
+ z = 1;
+ for(y=0;y<e;y++)
+ z*=2;
+
+ i+=z;
+ }
+ else
+ {
+ z = 5000000000000000000;
+ for(y = 1; y < -e; y++)
+ z /= 2;
+
+ f+=z;
+ }
+ }
+ e--;
+ }
+
+ if(s && n)
+ {
+ *(dst++) = '-';
+ n--;
+ }
+
+ x = libc_ulltoa(i, dst, n);
+ n-=x;
+ dst+=x;
+
+ if(n)
+ {
+ *(dst++) = '.';
+ n--;
+ if(n)
+ {
+ x = libc_ulltoa(f, dst, n<6?n:6);
+ n-=x;
+ dst+=x;
+
+ if(n)
+ *dst=0;
+ }
+ }
+ }
+}
+
+void libc_double_to_string(double fl, char *dst, int n)
+{
+ unsigned long long *p = (unsigned long long *)&fl;
+ unsigned long long i = 0;
+ unsigned long long f = 0;
+ unsigned long long m, s;
+ long long e;
+ int x, y;
+ unsigned long long z;
+
+ s = *p >> 63;
+
+ e = (*p >> 52) & 0x7ff;
+ //printf("%d\n", e);
+
+ m = *p & 0xfffffffffffff;
+
+ for(x=0;x<52;x++)
+ if(m&((unsigned long long)1<<(52-x))) putchar('1'); else putchar('0');
+
+ if(e == 255 && m == 0) // Infinity
+ {
+ if(s) strncpy(dst, "-inf", n);
+ else strncpy(dst, "inf", n);
+ }else if(e == 255 && m != 0) // NaN
+ {
+ strncpy(dst, "nan", n);
+ }
+ else
+ {
+ e -= 1023;
+ m |= (unsigned long long)1<<52;
+
+ for(x = 52; x >= 0; x--)
+ {
+ if(m & ((unsigned long long)1<<x))
+ {
+ if(e >= 0)
+ {
+ z = (long long)1<<e;
+
+ i+=z;
+ }
+ else
+ {
+ z = 5000000000000000000;
+ z >>= -(e + 1);
+
+ f+=z;
+ }
+ }
+ e--;
+ }
+
+ if(s && n)
+ {
+ *(dst++) = '-';
+ n--;
+ }
+
+ x = libc_ulltoa(i, dst, n);
+ n-=x;
+ dst+=x;
+
+ if(n)
+ {
+ *(dst++) = '.';
+ n--;
+ if(n)
+ libc_ulltoa(f, dst, n<6?n:6);
+ }
+ }
+}
+
+char libc_sprintf_floatbuf[64];
+
+int vsnprintf(char *string, unsigned int size, const char *fmt, va_list ap)
+{
+ int string_pos,fmt_pos;
+ int l;
+ unsigned long arg;
+ unsigned char *argcp;
+ unsigned char *argcp_tmp;
+ int directive_coming = 0;
+ int alternate_form = 0;
+ int flags = 0;
+ int argsize = 2; // int
+ int x, y;
+ unsigned long a, b;
+ int empty_digit;
+ int ssz = size - 1;
+ int zero_flag_imp = 0;
+ int pad_quantity = 0;
+ int last;
+
+ l = strlen(fmt);
+
+ string_pos = 0;
+
+ for(fmt_pos=0;fmt_pos<l;fmt_pos++)
+ {
+ if(directive_coming)
+ {
+ switch(fmt[fmt_pos])
+ {
+ case '%':
+ put_in_string(string, ssz, '%', string_pos++);
+ directive_coming = 0;
+ break;
+ case ' ':
+ flags |= SPRINTF_SPACE_FLAG;
+ break;
+ case '#': // Specify alternate form
+ flags |= SPRINTF_ALT_FLAG;
+ break;
+ case '+': // Specify sign in signed conversions
+ flags |= SPRINTF_SIGN_FLAG;
+ break;
+ case '0': // Padding with zeros...
+ if(zero_flag_imp == 0)
+ {
+ flags |= SPRINTF_ZERO_FLAG;
+ zero_flag_imp = 1;
+ //printf("Zero padding enabled!\n");
+ }
+ else
+ {
+ pad_quantity *= 10;
+ //printf("pad_quantity = %d\n", pad_quantity);
+ }
+ break;
+ case '1' ... '9': // '...' cases are a GNU extension,
+ // but they simplify a lot
+
+ pad_quantity *= 10;
+ pad_quantity += fmt[fmt_pos] - '0';
+ zero_flag_imp = 1;
+
+ //printf("pad_quantity = %d\n", pad_quantity);
+ break;
+ case '-': // Negative field flag
+ if(flags & SPRINTF_ZERO_FLAG)
+ flags &= ~SPRINTF_ZERO_FLAG;
+
+ flags |= SPRINTF_NEGFIELD_FLAG;
+ break;
+ case 'h': // Half argument size
+ if(argsize) argsize--;
+ break;
+ case 'l': // Double argument size
+ if(argsize < 2) argsize = 2;
+ //else if(argsize < SPRINTF_SIZE_LONG_LONG) argsize++;
+ break;
+ case 'd': // signed decimal
+ case 'i':
+ empty_digit = 1;
+
+ //printf("argsize = %d\n", argsize);
+
+ //if(argsize < SPRINTF_SIZE_LONG_LONG)
+ arg = (unsigned long)va_arg(ap, unsigned int);
+ //else
+ // arg = va_arg(ap, unsigned long);
+
+ if(get_arg_in_size(argsize, &arg, 1))
+ {
+ put_in_string(string, ssz, '-', string_pos++);
+ pad_quantity--;
+ }
+ else
+ {
+ if(flags & SPRINTF_SIGN_FLAG)
+ {
+ put_in_string(string, ssz, '+', string_pos++);
+ pad_quantity--;
+ }
+ }
+
+ /* Calculate how much padding we have to write */
+
+ /*y = 1;
+
+ for(x=0;x<=9;x++)
+ {
+ if(x == 0)
+ pad_quantity--;
+ else
+ {
+ if(arg / y)
+ pad_quantity--;
+ }
+
+ y *= 10;
+ }
+ if(pad_quantity < 0) pad_quantity = 0;*/
+
+ calculate_real_padding();
+
+ //printf("Actual pad quantity = %d\n", pad_quantity);
+
+
+
+ /*if(!(flags & SPRINTF_NEGFIELD_FLAG))
+ {
+ for(x = 0; x < pad_quantity; x++)
+ {
+ if(flags & SPRINTF_ZERO_FLAG)
+ put_in_string(string, ssz, '0', string_pos++);
+ else
+ put_in_string(string, ssz, ' ', string_pos++);
+ }
+ }*/
+
+ write_padding();
+
+ for(x=19;x>=0;x--)
+ {
+ a = 1;
+ for(y = 0; y<x; y++)
+ a *= 10;
+
+ b = (arg/a);
+
+ if(b>=1)
+ empty_digit = 0;
+
+ if(empty_digit == 0 || x == 0)
+ {
+ arg -= b*a;
+
+ put_in_string(string, ssz, b + '0', string_pos++);
+ }
+ }
+
+ /*if(flags & SPRINTF_NEGFIELD_FLAG)
+ {
+ for(x = 0; x < pad_quantity; x++)
+ put_in_string(string, ssz, ' ', string_pos++);
+ }*/
+ write_neg_padding();
+
+ directive_coming = 0;
+ break;
+ case 'u': // unsigned decimal
+ empty_digit = 1;
+
+ //if(argsize < SPRINTF_SIZE_LONG_LONG)
+ arg = (unsigned long)va_arg(ap, unsigned int);
+ //else
+ //arg = va_arg(ap, unsigned long long);
+
+ get_arg_in_size(argsize, &arg, 0);
+
+ calculate_real_padding();
+ write_padding();
+
+ for(x=19;x>=0;x--)
+ {
+ a = 1;
+ for(y = 0; y<x; y++)
+ a *= 10;
+
+
+
+ b = (arg/a);
+
+ if(b>=1)
+ empty_digit = 0;
+
+ if(empty_digit == 0 || x == 0)
+ {
+ arg -= b*a;
+
+ put_in_string(string, ssz, b + '0', string_pos++);
+ }
+ }
+
+ write_neg_padding();
+
+ directive_coming = 0;
+ break;
+ case 'x': // Hexadecimal
+ case 'X': // Hexadecimal with big letters
+ case 'p': // Hexadecimal with small letters with '0x' prefix
+ empty_digit = 1;
+
+ //if(argsize < SPRINTF_SIZE_LONG_LONG)
+ arg = (unsigned long)va_arg(ap, unsigned int);
+ //else
+ // arg = va_arg(ap, unsigned long int);
+
+ get_arg_in_size(argsize, &arg, 0);
+
+ if(fmt_pos == 'p')
+ flags |= SPRINTF_ALT_FLAG;
+
+ if(flags & SPRINTF_ALT_FLAG)
+ {
+ put_in_string(string, ssz, '0', string_pos++);
+
+ if(fmt[fmt_pos] == 'X')
+ put_in_string(string, ssz, 'X', string_pos++);
+ else
+ put_in_string(string, ssz, 'x', string_pos++);
+ }
+
+ calculate_real_padding_hex();
+ write_padding();
+
+ for(x=7;x>=0;x--)
+ {
+ y = arg >> (x << 2);
+ y &= 0xf;
+
+ if(y>=1)
+ empty_digit = 0;
+
+ if(empty_digit == 0 || x == 0)
+ {
+ if(y>=0 && y<=9)
+ put_in_string(string, ssz, y + '0', string_pos++);
+ else if(y>=0xA && y<=0xF)
+ {
+ if(fmt[fmt_pos] == 'X')
+ put_in_string(string, ssz, (y - 0xa) + 'A', string_pos++);
+ else
+ put_in_string(string, ssz, (y - 0xa) + 'a', string_pos++);
+ }
+ }
+ }
+
+ write_neg_padding();
+
+ directive_coming = 0;
+ break;
+ case 'c': // character
+ arg = va_arg(ap, int);
+
+ put_in_string(string, ssz, arg & 0xff, string_pos++);
+
+ directive_coming = 0;
+ break;
+ case 's': // string
+ argcp = va_arg(ap, char *);
+ argcp_tmp = argcp;
+
+ if(argcp == NULL)
+ {
+ // Non standard extension, but supported by Linux and the BSDs.
+
+ put_in_string(string, ssz, '(', string_pos++);
+ put_in_string(string, ssz, 'n', string_pos++);
+ put_in_string(string, ssz, 'u', string_pos++);
+ put_in_string(string, ssz, 'l', string_pos++);
+ put_in_string(string, ssz, 'l', string_pos++);
+ put_in_string(string, ssz, ')', string_pos++);
+
+ directive_coming = 0;
+ break;
+ }
+
+ while(*argcp_tmp)
+ {
+ if(pad_quantity > 0) pad_quantity--;
+ argcp_tmp++;
+ }
+
+ if(!(flags & SPRINTF_NEGFIELD_FLAG))
+ {
+ while(pad_quantity > 0)
+ {
+ put_in_string(string,ssz, ' ', string_pos++);
+ pad_quantity--;
+ }
+ }
+
+ while(*argcp)
+ {
+ put_in_string(string, ssz, *argcp, string_pos++);
+ argcp++;
+ }
+
+ if(flags & SPRINTF_NEGFIELD_FLAG)
+ {
+ while(pad_quantity > 0)
+ {
+ put_in_string(string,ssz, ' ', string_pos++);
+ pad_quantity--;
+ }
+ }
+
+ directive_coming = 0;
+ break;
+ case 'o': // Octal
+ empty_digit = 1;
+
+ //if(argsize < SPRINTF_SIZE_LONG_LONG)
+ arg = (unsigned long)va_arg(ap, unsigned int);
+ //else
+ // arg = va_arg(ap, unsigned long long);
+
+ for(x=21;x>=0;x--)
+ {
+ y = arg >> (x * 3);
+ y &= 0x7;
+
+ if(y>=1)
+ empty_digit = 0;
+
+ if(empty_digit == 0 || x == 0)
+ put_in_string(string, ssz, y + '0', string_pos++);
+ }
+
+ directive_coming = 0;
+ break;
+ case '@': // Binary
+ empty_digit = 1;
+
+ //if(argsize < SPRINTF_SIZE_LONG_LONG)
+ arg = (unsigned long)va_arg(ap, unsigned int);
+ //else
+ // arg = va_arg(ap, unsigned long long);
+
+ for(x=31;x>=0;x--)
+ {
+ y = (arg >> x);
+ y &= 1;
+
+ if(y>=1)
+ empty_digit = 0;
+
+ if(empty_digit == 0 || x == 0)
+ put_in_string(string, ssz, y + '0', string_pos++);
+ }
+
+ directive_coming = 0;
+ break;
+
+ case 'f':
+ libc_double_to_string(va_arg(ap, double), libc_sprintf_floatbuf, 64);
+
+ for(x=0;libc_sprintf_floatbuf[x]!=0;x++)
+ put_in_string(string, ssz, libc_sprintf_floatbuf[x], string_pos++);
+
+ directive_coming = 0;
+ break;
+ case 'n': // Number of characters written
+ *(va_arg(ap,unsigned int*)) = string_pos;
+
+ directive_coming = 0;
+ break;
+ // default
+ }
+ }
+ else
+ {
+ if(fmt[fmt_pos] == '%')
+ {
+ directive_coming = 1;
+ flags = 0;
+ argsize = 2;
+ pad_quantity = 0;
+ zero_flag_imp = 0;
+ }
+ else
+ put_in_string(string, ssz, fmt[fmt_pos], string_pos++);
+ }
+ }
+ string[string_pos] = 0;
+ return string_pos;
+}
+
+int vsprintf(char *string, const char *fmt, va_list ap)
+{
+ return vsnprintf(string, 0xffffffff, fmt, ap);
+}
+
+int sprintf(char *string, const char *fmt, ...)
+{
+ int r;
+
+ va_list ap;
+
+ va_start(ap, fmt);
+
+ r = vsprintf(string, fmt, ap);
+
+ va_end(ap);
+
+ return r;
+}
+
+int snprintf(char *string, unsigned int size, const char *fmt, ...)
+{
+ int r;
+
+ va_list ap;
+
+ va_start(ap, fmt);
+
+ r = vsnprintf(string, size, fmt, ap);
+
+ va_end(ap);
+
+ return r;
+}
diff --git a/libpsn00b/libc/printf.c b/libpsn00b/libc/vsprintf.c-old
index 7350648..9c68a1f 100644
--- a/libpsn00b/libc/printf.c
+++ b/libpsn00b/libc/vsprintf.c-old
@@ -356,7 +356,7 @@ void libc_double_to_string(double fl, char *dst, int n)
char libc_sprintf_floatbuf[64];
-int vsnprintf(char *string, unsigned int size, char *fmt, va_list ap)
+int vsnprintf(char *string, unsigned int size, const char *fmt, va_list ap)
{
int string_pos,fmt_pos;
int l;
@@ -752,12 +752,12 @@ int vsnprintf(char *string, unsigned int size, char *fmt, va_list ap)
return string_pos;
}
-int vsprintf(char *string, char *fmt, va_list ap)
+int vsprintf(char *string, const char *fmt, va_list ap)
{
return vsnprintf(string, 0xffffffff, fmt, ap);
}
-int sprintf(char *string, char *fmt, ...)
+int sprintf(char *string, const char *fmt, ...)
{
int r;
@@ -772,7 +772,7 @@ int sprintf(char *string, char *fmt, ...)
return r;
}
-int snprintf(char *string, unsigned int size, char *fmt, ...)
+int snprintf(char *string, unsigned int size, const char *fmt, ...)
{
int r;