Cleanup
This commit is contained in:
parent
e8d4a98c7b
commit
c746326eb3
@ -188,10 +188,10 @@ void detectAndProcessExceptionDumps(void)
|
||||
drawFormattedString(false, 10 + 10 * SPACING_X + 3 * i * SPACING_X, posYBottom, COLOR_WHITE, "%02X", *stackDump);
|
||||
}
|
||||
|
||||
char folderPath[36],
|
||||
char folderPath[12],
|
||||
path[36],
|
||||
fileName[] = "crash_dump_00010000.dmp";
|
||||
|
||||
fileName[24];
|
||||
|
||||
sprintf(folderPath, "dumps/arm%u", dumpHeader->processor);
|
||||
findDumpFile(folderPath, fileName);
|
||||
sprintf(path, "%s/%s", folderPath, fileName);
|
||||
|
558
source/fmt.c
558
source/fmt.c
@ -1,9 +1,3 @@
|
||||
// TuxSH's changes: add support for 64-bit numbers, remove floating-point code
|
||||
// TODO! fix left-padding handling with > 10 characters.
|
||||
|
||||
#include "fmt.h"
|
||||
#include "strings.h"
|
||||
|
||||
/* File : barebones/ee_printf.c
|
||||
This file contains an implementation of ee_printf that only requires a method to output a char to a UART without pulling in library code.
|
||||
|
||||
@ -37,375 +31,245 @@ This code is based on a file that contains the following:
|
||||
|
||||
*/
|
||||
|
||||
//#include <coremark.h>
|
||||
//#include <stdarg.h>
|
||||
/* TuxSH's changes: add support for 64-bit numbers, remove floating-point code
|
||||
TODO! fix left-padding handling with > 10 characters. */
|
||||
|
||||
#define ZEROPAD (1<<0) /* Pad with zero */
|
||||
#define SIGN (1<<1) /* Unsigned/signed long */
|
||||
#define PLUS (1<<2) /* Show plus */
|
||||
#define SPACE (1<<3) /* Spacer */
|
||||
#define LEFT (1<<4) /* Left justified */
|
||||
#define HEX_PREP (1<<5) /* 0x */
|
||||
#define UPPERCASE (1<<6) /* 'ABCDEF' */
|
||||
#include "fmt.h"
|
||||
#include "strings.h"
|
||||
|
||||
#define is_digit(c) ((c) >= '0' && (c) <= '9')
|
||||
#define ZEROPAD (1<<0) //Pad with zero
|
||||
#define SIGN (1<<1) //Unsigned/signed long
|
||||
#define PLUS (1<<2) //Show plus
|
||||
#define SPACE (1<<3) //Spacer
|
||||
#define LEFT (1<<4) //Left justified
|
||||
#define HEX_PREP (1<<5) //0x
|
||||
#define UPPERCASE (1<<6) //'ABCDEF'
|
||||
|
||||
static char *lower_digits = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
static char *upper_digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
#define IS_DIGIT(c) ((c) >= '0' && (c) <= '9')
|
||||
|
||||
/*
|
||||
static size_t strnlen(const char *s, size_t count);
|
||||
|
||||
static size_t strnlen(const char *s, size_t count)
|
||||
static u32 skipAtoi(const char **s)
|
||||
{
|
||||
const char *sc;
|
||||
for (sc = s; *sc != '\0' && count--; ++sc);
|
||||
return sc - s;
|
||||
}
|
||||
*/
|
||||
|
||||
static int ee_skip_atoi(const char **s)
|
||||
{
|
||||
int i = 0;
|
||||
while (is_digit(**s)) i = i*10 + *((*s)++) - '0';
|
||||
return i;
|
||||
u32 i = 0;
|
||||
while(IS_DIGIT(**s)) i = i * 10 + *((*s)++) - '0';
|
||||
return i;
|
||||
}
|
||||
|
||||
static char *ee_number(char *str, long long num, int base, int size, int precision, int type)
|
||||
static char *processNumber(char *str, s64 num, bool isHex, s32 size, s32 precision, u32 type)
|
||||
{
|
||||
char c, sign, tmp[66];
|
||||
char *dig = lower_digits;
|
||||
int i;
|
||||
if(type & LEFT) type &= ~ZEROPAD;
|
||||
|
||||
if (type & UPPERCASE) dig = upper_digits;
|
||||
if (type & LEFT) type &= ~ZEROPAD;
|
||||
if (base < 2 || base > 36) return 0;
|
||||
char sign = 0;
|
||||
|
||||
c = (type & ZEROPAD) ? '0' : ' ';
|
||||
sign = 0;
|
||||
if (type & SIGN)
|
||||
{
|
||||
if (num < 0)
|
||||
if(type & SIGN)
|
||||
{
|
||||
sign = '-';
|
||||
num = -num;
|
||||
size--;
|
||||
}
|
||||
else if (type & PLUS)
|
||||
{
|
||||
sign = '+';
|
||||
size--;
|
||||
}
|
||||
else if (type & SPACE)
|
||||
{
|
||||
sign = ' ';
|
||||
size--;
|
||||
}
|
||||
}
|
||||
|
||||
if (type & HEX_PREP)
|
||||
{
|
||||
if (base == 16)
|
||||
size -= 2;
|
||||
else if (base == 8)
|
||||
size--;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
if (num == 0)
|
||||
tmp[i++] = '0';
|
||||
else
|
||||
{
|
||||
while (num != 0)
|
||||
{
|
||||
tmp[i++] = dig[(unsigned long long)num % (unsigned long long)base];
|
||||
num = (long long)((unsigned long long)num / (unsigned long long) base);
|
||||
}
|
||||
}
|
||||
|
||||
if (i > precision) precision = i;
|
||||
size -= precision;
|
||||
if (!(type & (ZEROPAD | LEFT))) while (size-- > 0) *str++ = ' ';
|
||||
if (sign) *str++ = sign;
|
||||
|
||||
if (type & HEX_PREP)
|
||||
{
|
||||
if (base == 8)
|
||||
*str++ = '0';
|
||||
else if (base == 16)
|
||||
{
|
||||
*str++ = '0';
|
||||
*str++ = lower_digits[33];
|
||||
}
|
||||
}
|
||||
|
||||
if (!(type & LEFT)) while (size-- > 0) *str++ = c;
|
||||
while (i < precision--) *str++ = '0';
|
||||
while (i-- > 0) *str++ = tmp[i];
|
||||
while (size-- > 0) *str++ = ' ';
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static char *eaddr(char *str, unsigned char *addr, int size, int precision __attribute__((unused)), int type)
|
||||
{
|
||||
char tmp[24];
|
||||
char *dig = lower_digits;
|
||||
int i, len;
|
||||
|
||||
if (type & UPPERCASE) dig = upper_digits;
|
||||
len = 0;
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
if (i != 0) tmp[len++] = ':';
|
||||
tmp[len++] = dig[addr[i] >> 4];
|
||||
tmp[len++] = dig[addr[i] & 0x0F];
|
||||
}
|
||||
|
||||
if (!(type & LEFT)) while (len < size--) *str++ = ' ';
|
||||
for (i = 0; i < len; ++i) *str++ = tmp[i];
|
||||
while (len < size--) *str++ = ' ';
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static char *iaddr(char *str, unsigned char *addr, int size, int precision __attribute__((unused)), int type)
|
||||
{
|
||||
char tmp[24];
|
||||
int i, n, len;
|
||||
|
||||
len = 0;
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
if (i != 0) tmp[len++] = '.';
|
||||
n = addr[i];
|
||||
|
||||
if (n == 0)
|
||||
tmp[len++] = lower_digits[0];
|
||||
else
|
||||
{
|
||||
if (n >= 100)
|
||||
{
|
||||
tmp[len++] = lower_digits[n / 100];
|
||||
n = n % 100;
|
||||
tmp[len++] = lower_digits[n / 10];
|
||||
n = n % 10;
|
||||
}
|
||||
else if (n >= 10)
|
||||
{
|
||||
tmp[len++] = lower_digits[n / 10];
|
||||
n = n % 10;
|
||||
}
|
||||
|
||||
tmp[len++] = lower_digits[n];
|
||||
}
|
||||
}
|
||||
|
||||
if (!(type & LEFT)) while (len < size--) *str++ = ' ';
|
||||
for (i = 0; i < len; ++i) *str++ = tmp[i];
|
||||
while (len < size--) *str++ = ' ';
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static int ee_vsprintf(char *buf, const char *fmt, va_list args)
|
||||
{
|
||||
int len;
|
||||
long long num;
|
||||
int i, base;
|
||||
char *str;
|
||||
char *s;
|
||||
int flags; // Flags to number()
|
||||
|
||||
int field_width; // Width of output field
|
||||
int precision; // Min. # of digits for integers; max number of chars for from string
|
||||
int qualifier; // 'h', 'l', or 'L' for integer fields
|
||||
int qualifier2;
|
||||
|
||||
for (str = buf; *fmt; fmt++)
|
||||
{
|
||||
if (*fmt != '%')
|
||||
{
|
||||
*str++ = *fmt;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Process flags
|
||||
flags = 0;
|
||||
repeat:
|
||||
fmt++; // This also skips first '%'
|
||||
switch (*fmt)
|
||||
{
|
||||
case '-': flags |= LEFT; goto repeat;
|
||||
case '+': flags |= PLUS; goto repeat;
|
||||
case ' ': flags |= SPACE; goto repeat;
|
||||
case '#': flags |= HEX_PREP; goto repeat;
|
||||
case '0': flags |= ZEROPAD; goto repeat;
|
||||
}
|
||||
|
||||
// Get field width
|
||||
field_width = -1;
|
||||
if (is_digit(*fmt))
|
||||
field_width = ee_skip_atoi(&fmt);
|
||||
else if (*fmt == '*')
|
||||
{
|
||||
fmt++;
|
||||
field_width = va_arg(args, int);
|
||||
if (field_width < 0)
|
||||
{
|
||||
field_width = -field_width;
|
||||
flags |= LEFT;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the precision
|
||||
precision = -1;
|
||||
if (*fmt == '.')
|
||||
{
|
||||
++fmt;
|
||||
if (is_digit(*fmt))
|
||||
precision = ee_skip_atoi(&fmt);
|
||||
else if (*fmt == '*')
|
||||
{
|
||||
++fmt;
|
||||
precision = va_arg(args, int);
|
||||
}
|
||||
if (precision < 0) precision = 0;
|
||||
}
|
||||
|
||||
// Get the conversion qualifier
|
||||
qualifier = qualifier2 = -1;
|
||||
if(*fmt == 'L')
|
||||
qualifier = *fmt++;
|
||||
else if (*fmt == 'l')
|
||||
{
|
||||
qualifier = *fmt++;
|
||||
if(*fmt == 'l') qualifier2 = *fmt++;
|
||||
}
|
||||
else if (*fmt == 'h')
|
||||
{
|
||||
qualifier = *fmt++;
|
||||
if(*fmt == 'h') qualifier2 = *fmt++;
|
||||
}
|
||||
|
||||
// Default base
|
||||
base = 10;
|
||||
|
||||
switch (*fmt)
|
||||
{
|
||||
case 'c':
|
||||
if (!(flags & LEFT)) while (--field_width > 0) *str++ = ' ';
|
||||
*str++ = (unsigned char) va_arg(args, int);
|
||||
while (--field_width > 0) *str++ = ' ';
|
||||
continue;
|
||||
|
||||
case 's':
|
||||
s = va_arg(args, char *);
|
||||
if (!s) s = "<NULL>";
|
||||
if(precision != -1)
|
||||
len = strnlen(s, precision);
|
||||
else
|
||||
len = strlen(s);
|
||||
if (!(flags & LEFT)) while (len < field_width--) *str++ = ' ';
|
||||
for (i = 0; i < len; ++i) *str++ = *s++;
|
||||
while (len < field_width--) *str++ = ' ';
|
||||
continue;
|
||||
|
||||
case 'p':
|
||||
if (field_width == -1)
|
||||
if(num < 0)
|
||||
{
|
||||
field_width = 2 * sizeof(void *);
|
||||
flags |= ZEROPAD;
|
||||
sign = '-';
|
||||
num = -num;
|
||||
size--;
|
||||
}
|
||||
else if(type & PLUS)
|
||||
{
|
||||
sign = '+';
|
||||
size--;
|
||||
}
|
||||
else if(type & SPACE)
|
||||
{
|
||||
sign = ' ';
|
||||
size--;
|
||||
}
|
||||
str = ee_number(str, (unsigned long) va_arg(args, void *), 16, field_width, precision, flags);
|
||||
continue;
|
||||
|
||||
case 'A':
|
||||
flags |= UPPERCASE;
|
||||
|
||||
case 'a':
|
||||
if (qualifier == 'l')
|
||||
str = eaddr(str, va_arg(args, unsigned char *), field_width, precision, flags);
|
||||
else
|
||||
str = iaddr(str, va_arg(args, unsigned char *), field_width, precision, flags);
|
||||
continue;
|
||||
|
||||
// Integer number formats - set up the flags and "break"
|
||||
case 'o':
|
||||
base = 8;
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
flags |= UPPERCASE;
|
||||
|
||||
case 'x':
|
||||
base = 16;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'i':
|
||||
flags |= SIGN;
|
||||
|
||||
case 'u':
|
||||
break;
|
||||
|
||||
default:
|
||||
if (*fmt != '%') *str++ = '%';
|
||||
if (*fmt)
|
||||
*str++ = *fmt;
|
||||
else
|
||||
--fmt;
|
||||
continue;
|
||||
}
|
||||
|
||||
// bugfixes here:
|
||||
if(type & HEX_PREP && isHex) size -= 2;
|
||||
|
||||
if(flags & SIGN)
|
||||
{
|
||||
if (qualifier == 'l' && qualifier2 == 'l')
|
||||
num = va_arg(args, long long int);
|
||||
else if(qualifier == 'l')
|
||||
num = va_arg(args, long int);
|
||||
/* else if(qualifier == 'h' && qualifier == 'h')
|
||||
num = va_arg(args, signed char);
|
||||
else if(qualifier == 'h')
|
||||
num = va_arg(args, short);*/
|
||||
else
|
||||
num = va_arg(args, int);
|
||||
}
|
||||
static const char *lowerDigits = "0123456789abcdef",
|
||||
*upperDigits = "0123456789ABCDEF";
|
||||
|
||||
s32 i = 0;
|
||||
char tmp[66],
|
||||
c = (type & ZEROPAD) ? '0' : ' ';
|
||||
const char *dig = (type & UPPERCASE) ? upperDigits : lowerDigits;
|
||||
|
||||
if(num == 0) tmp[i++] = '0';
|
||||
else
|
||||
{
|
||||
if (qualifier == 'l' && qualifier2 == 'l')
|
||||
num = va_arg(args, unsigned long long int);
|
||||
else if(qualifier == 'l')
|
||||
num = va_arg(args, unsigned long int);
|
||||
/* else if(qualifier == 'h' && qualifier == 'h')
|
||||
num = va_arg(args, unsigned char);
|
||||
else if(qualifier == 'h')
|
||||
num = va_arg(args, unsigned short);*/
|
||||
else
|
||||
num = va_arg(args, unsigned int);
|
||||
while (num != 0)
|
||||
{
|
||||
u64 base = isHex ? 16ULL : 10ULL;
|
||||
tmp[i++] = dig[(u64)num % base];
|
||||
num = (s64)((u64)num / base);
|
||||
}
|
||||
}
|
||||
|
||||
str = ee_number(str, num, base, field_width, precision, flags);
|
||||
}
|
||||
if(i > precision) precision = i;
|
||||
size -= precision;
|
||||
if(!(type & (ZEROPAD | LEFT))) while(size-- > 0) *str++ = ' ';
|
||||
if(sign) *str++ = sign;
|
||||
|
||||
*str = '\0';
|
||||
return str - buf;
|
||||
if(type & HEX_PREP && isHex)
|
||||
{
|
||||
*str++ = '0';
|
||||
*str++ = 'x';
|
||||
}
|
||||
|
||||
if(!(type & LEFT)) while(size-- > 0) *str++ = c;
|
||||
while(i < precision--) *str++ = '0';
|
||||
while(i-- > 0) *str++ = tmp[i];
|
||||
while(size-- > 0) *str++ = ' ';
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
int vsprintf(char *buf, const char *fmt, va_list args)
|
||||
u32 vsprintf(char *buf, const char *fmt, va_list args)
|
||||
{
|
||||
return ee_vsprintf(buf, fmt, args);
|
||||
char *str;
|
||||
|
||||
for(str = buf; *fmt; fmt++)
|
||||
{
|
||||
if(*fmt != '%')
|
||||
{
|
||||
*str++ = *fmt;
|
||||
continue;
|
||||
}
|
||||
|
||||
//Process flags
|
||||
u32 flags = 0; //Flags to number()
|
||||
bool loop = false;
|
||||
|
||||
while(!loop)
|
||||
{
|
||||
switch(*++fmt)
|
||||
{
|
||||
case '-': flags |= LEFT; break;
|
||||
case '+': flags |= PLUS; break;
|
||||
case ' ': flags |= SPACE; break;
|
||||
case '#': flags |= HEX_PREP; break;
|
||||
case '0': flags |= ZEROPAD; break;
|
||||
default: loop = true; break;
|
||||
}
|
||||
}
|
||||
|
||||
//Get field width
|
||||
s32 fieldWidth = -1; //Width of output field
|
||||
if(IS_DIGIT(*fmt)) fieldWidth = skipAtoi(&fmt);
|
||||
else if(*fmt == '*')
|
||||
{
|
||||
fmt++;
|
||||
|
||||
fieldWidth = va_arg(args, s32);
|
||||
|
||||
if(fieldWidth < 0)
|
||||
{
|
||||
fieldWidth = -fieldWidth;
|
||||
flags |= LEFT;
|
||||
}
|
||||
}
|
||||
|
||||
//Get the precision
|
||||
s32 precision = -1; //Min. # of digits for integers; max number of chars for from string
|
||||
if(*fmt == '.')
|
||||
{
|
||||
fmt++;
|
||||
|
||||
if(IS_DIGIT(*fmt)) precision = skipAtoi(&fmt);
|
||||
else if(*fmt == '*')
|
||||
{
|
||||
fmt++;
|
||||
precision = va_arg(args, s32);
|
||||
}
|
||||
|
||||
if(precision < 0) precision = 0;
|
||||
}
|
||||
|
||||
//Get the conversion qualifier
|
||||
bool isLongLong = false;
|
||||
if(*fmt == 'l')
|
||||
{
|
||||
if(*++fmt == 'l')
|
||||
{
|
||||
fmt++;
|
||||
isLongLong = true;
|
||||
}
|
||||
}
|
||||
|
||||
//Default base
|
||||
bool isHex = false;
|
||||
|
||||
switch(*fmt)
|
||||
{
|
||||
case 'c':
|
||||
if(!(flags & LEFT)) while(--fieldWidth > 0) *str++ = ' ';
|
||||
*str++ = (u8)va_arg(args, s32);
|
||||
while(--fieldWidth > 0) *str++ = ' ';
|
||||
continue;
|
||||
|
||||
case 's':
|
||||
{
|
||||
char *s = va_arg(args, char *);
|
||||
if(!s) s = "<NULL>";
|
||||
u32 len = (precision != -1) ? strnlen(s, precision) : strlen(s);
|
||||
if(!(flags & LEFT)) while((s32)len < fieldWidth--) *str++ = ' ';
|
||||
for(u32 i = 0; i < len; i++) *str++ = *s++;
|
||||
while((s32)len < fieldWidth--) *str++ = ' ';
|
||||
continue;
|
||||
}
|
||||
|
||||
case 'p':
|
||||
if(fieldWidth == -1)
|
||||
{
|
||||
fieldWidth = 8;
|
||||
flags |= ZEROPAD;
|
||||
}
|
||||
str = processNumber(str, (s64)va_arg(args, u32), true, fieldWidth, precision, flags);
|
||||
continue;
|
||||
|
||||
//Integer number formats - set up the flags and "break"
|
||||
case 'X':
|
||||
flags |= UPPERCASE;
|
||||
|
||||
case 'x':
|
||||
isHex = true;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'i':
|
||||
flags |= SIGN;
|
||||
|
||||
case 'u':
|
||||
break;
|
||||
|
||||
default:
|
||||
if(*fmt != '%') *str++ = '%';
|
||||
if(*fmt) *str++ = *fmt;
|
||||
else fmt--;
|
||||
continue;
|
||||
}
|
||||
|
||||
s64 num;
|
||||
|
||||
if(flags & SIGN)
|
||||
{
|
||||
if(isLongLong) num = va_arg(args, s64);
|
||||
else num = va_arg(args, s32);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(isLongLong) num = va_arg(args, u64);
|
||||
else num = va_arg(args, u32);
|
||||
}
|
||||
|
||||
str = processNumber(str, num, isHex, fieldWidth, precision, flags);
|
||||
}
|
||||
|
||||
*str = 0;
|
||||
return str - buf;
|
||||
}
|
||||
|
||||
int sprintf(char *buf, const char *fmt, ...)
|
||||
u32 sprintf(char *buf, const char *fmt, ...)
|
||||
{
|
||||
int n = 0;
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
n = ee_vsprintf(buf, fmt, args);
|
||||
u32 res = vsprintf(buf, fmt, args);
|
||||
va_end(args);
|
||||
return n;
|
||||
return res;
|
||||
}
|
||||
|
@ -2,5 +2,5 @@
|
||||
#include "memory.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
int vsprintf(char *buf, const char *fmt, va_list args);
|
||||
int sprintf(char *buf, const char *fmt, ...);
|
||||
u32 vsprintf(char *buf, const char *fmt, va_list args);
|
||||
u32 sprintf(char *buf, const char *fmt, ...);
|
||||
|
@ -35,6 +35,14 @@ typedef volatile u8 vu8;
|
||||
typedef volatile u16 vu16;
|
||||
typedef volatile u32 vu32;
|
||||
typedef volatile u64 vu64;
|
||||
typedef int8_t s8;
|
||||
typedef int16_t s16;
|
||||
typedef int32_t s32;
|
||||
typedef int64_t s64;
|
||||
typedef volatile s8 vs8;
|
||||
typedef volatile s16 vs16;
|
||||
typedef volatile s32 vs32;
|
||||
typedef volatile s64 vs64;
|
||||
|
||||
#include "3dsheaders.h"
|
||||
|
||||
|
Reference in New Issue
Block a user