This commit is contained in:
Aurora Wright 2017-05-07 23:18:26 +02:00
parent e8d4a98c7b
commit c746326eb3
4 changed files with 224 additions and 352 deletions

View File

@ -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);

View File

@ -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;
}

View File

@ -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, ...);

View File

@ -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"