mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-13 18:17:39 -04:00
Implement a much more capable vuprintf()
New support as well as some buggy support fixed. Still no floating point support if ever that would be desired. Support (*): * Flags: '-', '+', ' ', '#', '0' * Width and precision: 'n', '.n', '*' and '.*' * Length modifiers: 'hh', 'h', 'j', 'l', 'll', 't', 'z' * Radix: 'c', 'd', 'i', 'n', 'o', 'p/P', 's', 'u', 'x/X' (*) Provision exists to switch lesser-used stuff on or off or when certain functionality isn't desired (bootloader?). The compulsory radixes are everything but 'o', 'n', 'p/P' and 'x/X' with length modifiers being optional. The default setup is 'l', 'z', 'c', 'd', 'p/P', 's', 'u', 'x/X'. * Move fdprintf() to its own file. It was in a strange place. * Make callers compatible and fix a couple snprintf() bugs while at it. Could smush it down in size but I'm gonna get over the binsize neurosis and just the let optimizer do its thing. Change-Id: Ibdc613a9b6775802c188b29b9dd46c568c94f7c3
This commit is contained in:
parent
52af55eee8
commit
5c9688961e
8 changed files with 1129 additions and 337 deletions
|
@ -18,74 +18,94 @@
|
|||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Minimal printf and snprintf formatting functions
|
||||
*
|
||||
* These support %c %s %d and %x
|
||||
* Field width and zero-padding flag only
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <limits.h>
|
||||
#include "format.h"
|
||||
#include <errno.h>
|
||||
#include "vuprintf.h"
|
||||
|
||||
/* ALSA library requires a more advanced snprintf, so let's not
|
||||
override it in simulator for Linux. Note that Cygwin requires
|
||||
our snprintf or it produces garbled output after a while. */
|
||||
|
||||
struct for_snprintf {
|
||||
unsigned char *ptr; /* where to store it */
|
||||
size_t bytes; /* amount already stored */
|
||||
size_t max; /* max amount to store */
|
||||
char *ptr; /* where to store it */
|
||||
int rem; /* unwritten buffer remaining */
|
||||
};
|
||||
|
||||
static int sprfunc(void *ptr, unsigned char letter)
|
||||
static int sprfunc(void *ptr, int letter)
|
||||
{
|
||||
struct for_snprintf *pr = (struct for_snprintf *)ptr;
|
||||
if(pr->bytes < pr->max) {
|
||||
*pr->ptr = letter;
|
||||
pr->ptr++;
|
||||
pr->bytes++;
|
||||
return true;
|
||||
|
||||
if (pr->rem > 0) {
|
||||
if (--pr->rem == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*pr->ptr++ = letter;
|
||||
return 1;
|
||||
}
|
||||
return false; /* filled buffer */
|
||||
}
|
||||
else {
|
||||
if (pr->rem == -INT_MAX) {
|
||||
pr->rem = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int snprintf(char *buf, size_t size, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
struct for_snprintf pr;
|
||||
|
||||
pr.ptr = (unsigned char *)buf;
|
||||
pr.bytes = 0;
|
||||
pr.max = size;
|
||||
|
||||
va_start(ap, fmt);
|
||||
format(sprfunc, &pr, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
/* make sure it ends with a trailing zero */
|
||||
pr.ptr[(pr.bytes < pr.max) ? 0 : -1] = '\0';
|
||||
|
||||
return pr.bytes;
|
||||
--pr->rem;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
|
||||
{
|
||||
struct for_snprintf pr;
|
||||
if (size <= INT_MAX) {
|
||||
int bytes;
|
||||
struct for_snprintf pr;
|
||||
|
||||
pr.ptr = (unsigned char *)buf;
|
||||
pr.bytes = 0;
|
||||
pr.max = size;
|
||||
pr.ptr = buf;
|
||||
pr.rem = size;
|
||||
|
||||
format(sprfunc, &pr, fmt, ap);
|
||||
bytes = vuprintf(sprfunc, &pr, fmt, ap);
|
||||
|
||||
/* make sure it ends with a trailing zero */
|
||||
pr.ptr[(pr.bytes < pr.max) ? 0 : -1] = '\0';
|
||||
|
||||
return pr.bytes;
|
||||
if (size) {
|
||||
*pr.ptr = '\0';
|
||||
}
|
||||
else if (pr.rem > 0) {
|
||||
goto overflow;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
overflow:
|
||||
errno = EOVERFLOW;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int snprintf(char *buf, size_t size, const char *fmt, ...)
|
||||
{
|
||||
if (size <= INT_MAX) {
|
||||
int bytes;
|
||||
struct for_snprintf pr;
|
||||
va_list ap;
|
||||
|
||||
pr.ptr = buf;
|
||||
pr.rem = size;
|
||||
|
||||
va_start(ap, fmt);
|
||||
bytes = vuprintf(sprfunc, &pr, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (size) {
|
||||
*pr.ptr = '\0';
|
||||
}
|
||||
else if (pr.rem > 0) {
|
||||
goto overflow;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
overflow:
|
||||
errno = EOVERFLOW;
|
||||
return -1;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue