Pushing bugs
This commit is contained in:
parent
a362655af2
commit
241eeb64cb
|
@ -34,15 +34,16 @@
|
|||
//
|
||||
enum
|
||||
{
|
||||
BF_LINE = 1, // Line-buffered
|
||||
BF_FILE = 1<<1, // Linked to a file
|
||||
BF_BALLOC = 1<<2, // Buffer structure was malloc'd
|
||||
BF_SALLOC = 1<<3, // Internal buffer was malloc'd
|
||||
BF_FONCLOSE = 1<<4, // Flush on close
|
||||
BF_AUTOSCROLL = 1<<5, // Scroll-down automatically
|
||||
BF_TERM = 1, // Terminal buffer
|
||||
BF_LINE = 1<<1, // Line-buffered
|
||||
BF_FILE = 1<<2, // Linked to a file
|
||||
BF_BALLOC = 1<<3, // Buffer structure was malloc'd
|
||||
BF_SALLOC = 1<<4, // Internal buffer was malloc'd
|
||||
BF_FONCLOSE = 1<<5, // Flush on close
|
||||
BF_AUTOSCROLL = 1<<6, // Scroll-down automatically
|
||||
|
||||
BF_EOF = 1<<6, // End of file reached
|
||||
BF_ERR = 1<<7, // An error happened
|
||||
BF_EOF = 1<<7, // End of file reached
|
||||
BF_ERR = 1<<8, // An error happened
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -61,7 +62,7 @@ enum
|
|||
typedef struct Buffer_t Buffer_t;
|
||||
|
||||
//
|
||||
// For line buffers, the flusher by bputc() is called every '\n'
|
||||
// For line/terminal buffers, the flusher by bputc() is called every '\n'
|
||||
// For pure buffers, the flusher is called by bputc() after it fills
|
||||
// the buffer (unless flush-on-close is enabled)
|
||||
//
|
||||
|
@ -90,7 +91,7 @@ struct Buffer_t
|
|||
|
||||
BFlusher_t flusher; // See above
|
||||
|
||||
// The following parameters are only used in line buf mode
|
||||
// The following parameters are only used in terminal buf mode
|
||||
|
||||
int lastLF; // Characters since beginning of line
|
||||
int lineLen; // Line length (for line buffers)
|
||||
|
@ -98,14 +99,16 @@ struct Buffer_t
|
|||
// size/(lineLen*nLines) - 1 playback buffers
|
||||
};
|
||||
|
||||
extern Buffer_t *BStdOut, *BStdDbg;
|
||||
extern Buffer_t *BStdIn, *BStdOut, *BStdDbg;
|
||||
|
||||
error_t BCloseBuf(Buffer_t *);
|
||||
void BFlushOnClose(Buffer_t *);
|
||||
// For pure buffers only
|
||||
void BEnableLineBuffering(Buffer_t *);
|
||||
void BDisaleLineBuffering(Buffer_t *);
|
||||
|
||||
// For terminal buffers only
|
||||
error_t BScrollDownBuf(Buffer_t *);
|
||||
void BEnableAutoScroll(Buffer_t *);
|
||||
void BDisableAutoScroll(Buffer_t *);
|
||||
|
||||
//
|
||||
// Buffer creation functions
|
||||
//
|
||||
|
@ -116,34 +119,32 @@ void BDisableAutoScroll(Buffer_t *);
|
|||
// If source==NULL, malloc's the buffer
|
||||
// BCloseBuf() handles the de-allocations
|
||||
//
|
||||
error_t BCloseBuf(Buffer_t *);
|
||||
|
||||
// Creates a pure buffer of a given size
|
||||
error_t BOpenPureBuf(Buffer_t **pbuf, int mode, size_t size);
|
||||
error_t BOpenPureBufEx(Buffer_t **, char *source, int mode, size_t,
|
||||
BFlusher_t);
|
||||
|
||||
// Creates a lined buffer of pbCount*nLines lines each
|
||||
// Creates a terminal buffer of pbCount*nLines lines each
|
||||
// of lineLen length (pb = playback buffer, for scrolling up)
|
||||
error_t BOpenLineBuf(Buffer_t **pbuf, int mode,
|
||||
error_t BOpenTermBuf(Buffer_t **pbuf, int mode,
|
||||
int lineLen, int nLines, int pbCount);
|
||||
error_t BOpenLineBufEx(Buffer_t **pbuf, char *source, int mode,
|
||||
error_t BOpenTermBufEx(Buffer_t **pbuf, char *source, int mode,
|
||||
int lineLen, int nLines, int pbCount, BFlusher_t);
|
||||
|
||||
int BGetFlags(Buffer_t *);
|
||||
int BGetState(Buffer_t *);
|
||||
int BGetLineLen(Buffer_t *);
|
||||
void BSetLineLen(Buffer_t *, int);
|
||||
|
||||
error_t BFlushBuf(Buffer_t *);
|
||||
error_t BPutOnBuf(Buffer_t *, uchar);
|
||||
error_t BPrintOnBuf(Buffer_t *, const char *fmt, ...);
|
||||
error_t BPrintOnBufV(Buffer_t *, const char *fmt, va_list);
|
||||
|
||||
void BLockBuf(Buffer_t *);
|
||||
void BUnlockBuf(Buffer_t *);
|
||||
bool BTrylockBuf(Buffer_t *);
|
||||
|
||||
error_t BFlushBuf(Buffer_t *);
|
||||
error_t BScrollDownBuf(Buffer_t *);
|
||||
error_t BPutOnBuf(Buffer_t *, uchar);
|
||||
error_t BPrintOnBuf(Buffer_t *, const char *fmt, ...);
|
||||
error_t BPrintOnBufV(Buffer_t *, const char *fmt, va_list);
|
||||
|
||||
// Internal, non-locking functions; don't use unless you
|
||||
// have a good reason why
|
||||
error_t bputc(Buffer_t *buf, uchar ch);
|
||||
|
|
|
@ -170,6 +170,14 @@ noreturn void KeStartPanic(const char *, ...);
|
|||
#define BUG() XBUG('B')
|
||||
#define BUGON(x) if(x)BUG()
|
||||
|
||||
#define __GET_GETRIP() \
|
||||
__attribute__((__noinline__)) \
|
||||
static ulong __getrip() \
|
||||
{ return (size_t)__builtin_return_address(0); }
|
||||
|
||||
#define __PRINT_RIP() \
|
||||
DebugLog("%s.RIP=%p\n",__func__,__getrip())
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#endif
|
||||
|
|
|
@ -32,7 +32,9 @@
|
|||
//----------------------------------------------------------------------------//
|
||||
|
||||
// Address of the heap
|
||||
void *_heap_start;
|
||||
extern void *_heap_start;
|
||||
extern void *_heap_end;
|
||||
extern size_t _heap_max;
|
||||
|
||||
void MmInitHeap(void);
|
||||
|
||||
|
|
|
@ -75,22 +75,22 @@ noreturn void BtStartKern(multiboot_info_t *mbInfo, uint mbMagic, void *codeSeg)
|
|||
|
||||
// Several inits
|
||||
MmInitHeap();
|
||||
PsInitSched();
|
||||
//PsInitSched();
|
||||
|
||||
// Interrupts launching
|
||||
IdtSetup();
|
||||
KeEnableIRQs();
|
||||
|
||||
// Drivers enabling
|
||||
IoEnableRtc();
|
||||
IoEnableKeyb();
|
||||
|
||||
IoGetRtcTimeChar();
|
||||
IoPrintRtcTime();
|
||||
|
||||
IoDoStarWars();
|
||||
// IoDoStarWars();
|
||||
|
||||
KernLog("Goodbye at %s\n", IoGetRtcTimeChar());
|
||||
|
||||
// End this machine's suffering
|
||||
BStdOut->flusher(BStdOut);
|
||||
BFlushBuf(BStdOut);
|
||||
KeCrashSystem();
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ char ScanCodes[100] = { 0 };
|
|||
void KeybPrint(char code)
|
||||
{
|
||||
if (code) {
|
||||
bprintf(BStdOut, "%c", ScanCodes[(int)code]);
|
||||
bputc(BStdOut, ScanCodes[(int)code]);
|
||||
//bprintf(BStdOut, "%x ", code);
|
||||
BStdOut->flusher(BStdOut);
|
||||
}
|
||||
|
@ -51,7 +51,8 @@ void ScanCodesInit(void)
|
|||
ScanCodes[0x0B] = '0';
|
||||
ScanCodes[0x0C] = ' ';
|
||||
ScanCodes[0x0D] = '+';
|
||||
ScanCodes[0x0E] = ' ';
|
||||
ScanCodes[0x0E] = 0x8;
|
||||
ScanCodes[0x0F] = '\t';
|
||||
|
||||
ScanCodes[0x10] = 'a';
|
||||
ScanCodes[0x11] = 'z';
|
||||
|
@ -113,13 +114,29 @@ void KeybHandler(ISRFrame_t *regs)
|
|||
IoSendEOItoPIC(0x21);
|
||||
}
|
||||
|
||||
void IoCreateInputBuffer(void)
|
||||
{
|
||||
error_t rc;
|
||||
|
||||
rc = BOpenPureBuf(&BStdIn, BS_RDWR, 4 * KB);
|
||||
|
||||
if (rc) KeStartPanic("Couldn't create BStdIn");
|
||||
|
||||
BEnableLineBuffering(BStdIn);
|
||||
}
|
||||
|
||||
void IoEnableKeyb(void)
|
||||
{
|
||||
ulong flags = KePauseIRQs();
|
||||
|
||||
IdtRegisterIsr(KeybHandler, 0x21);
|
||||
char readedInterruptConfig = IoReadByteFromPort(0x21);
|
||||
IoWriteByteOnPort(0x21, 0xFD & readedInterruptConfig);
|
||||
|
||||
KeRestoreIRQs(flags);
|
||||
|
||||
IoEnableNMI();
|
||||
ScanCodesInit();
|
||||
|
||||
IoCreateInputBuffer();
|
||||
}
|
||||
|
|
|
@ -164,7 +164,8 @@ void IoPrintRtcTime(void)
|
|||
char* IoGetRtcTimeChar(void)
|
||||
{
|
||||
Time_t *RtcTime = IoGetRtcTime();
|
||||
sprintf(IoTimeChar, "%hhd/%hhd/%hd ; %hhd:%hhd:%hhd",
|
||||
snprintf(IoTimeChar, sizeof(IoTimeChar),
|
||||
"%02d/%02d/%02d ; %02d:%02d:%02d",
|
||||
RtcTime->day,
|
||||
RtcTime->month,
|
||||
RtcTime->year + RtcTime->century*100,
|
||||
|
|
|
@ -90,7 +90,7 @@ error_t IoInitVGABuffer(void)
|
|||
|
||||
BStdOut = &bvgabufstruct;
|
||||
|
||||
BOpenLineBufEx(&BStdOut,
|
||||
BOpenTermBufEx(&BStdOut,
|
||||
bvgabufsrc, BS_WRONLY,
|
||||
BtVideoInfo.framebufferWidth,
|
||||
BtVideoInfo.framebufferHeight,
|
||||
|
|
|
@ -26,11 +26,14 @@
|
|||
#include <kernel/heap.h>
|
||||
#include <extras/locks.h>
|
||||
|
||||
// Least address out of the heap
|
||||
static void *_heap_end;
|
||||
// Start address of the heap
|
||||
void *_heap_start;
|
||||
|
||||
// End of the heap
|
||||
/*static*/ void *_heap_end;
|
||||
|
||||
// Maximal value of the heap
|
||||
static size_t _heap_max;
|
||||
/*static*/ size_t _heap_max;
|
||||
|
||||
// Lock NOT used internally, but used by KalAllocMemory() & co.
|
||||
static Lock_t _heap_lock = ExINITLOCK(KLOCK_SPINLOCK);
|
||||
|
@ -114,6 +117,7 @@ error_t MmGrowHeap(size_t req)
|
|||
assert(req % alignof(QWORD) == 0);
|
||||
|
||||
if ((size_t)_heap_end + req > (size_t)_heap_start + _heap_max) {
|
||||
assert(!"Can't extend heap that much");
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -130,6 +134,7 @@ error_t MmShrinkHeap(size_t req)
|
|||
assert(req % alignof(QWORD) == 0);
|
||||
|
||||
if (req > (size_t)_heap_end - (size_t)_heap_start) {
|
||||
assert(!"Can't shrink heap that much");
|
||||
return EADDRINUSE;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ error_t KalAllocMemoryEx(void **ptr, size_t req, int flags, size_t align)
|
|||
{
|
||||
error_t rc;
|
||||
size_t brk;
|
||||
extern void *_heap_start;
|
||||
|
||||
if (align == 0) align = M_DEFAULT_ALIGNMENT;
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ static error_t InitMemoryMap(void)
|
|||
if ((BtMemoryInfo.upMemory / (MB/KB)) <= MINIMUM_RAM_SIZE)
|
||||
return ENOMEM;
|
||||
|
||||
// Ok then we can work ------------------------------------------------------ //
|
||||
// Ok then we can work
|
||||
|
||||
// the memory map provided by GRUB via the BIOS
|
||||
currentEntry = (multiboot_memory_map_t*)BtMemoryInfo.mapAddr;
|
||||
|
|
|
@ -392,7 +392,7 @@ error_t vbprintf(Buffer_t *buf, const char *fmt, va_list ap)
|
|||
// Carry on to next modifier
|
||||
}
|
||||
|
||||
// Assert rc for debugging purposes
|
||||
// Assert !rc for debugging purposes
|
||||
assert(!rc);
|
||||
|
||||
return rc;
|
||||
|
|
|
@ -34,7 +34,6 @@ error_t BPutOnBuf(Buffer_t *buf, uchar ch)
|
|||
assert(buf && buf->initDone == INITOK);
|
||||
|
||||
if (!buf) return EINVAL;
|
||||
if (buf->flags & (BF_EOF|BF_ERR)) return EENDF;
|
||||
if (buf->state != BS_RDWR && buf->state != BS_WRONLY) {
|
||||
return EBADF;
|
||||
}
|
||||
|
@ -52,10 +51,12 @@ error_t bputc(Buffer_t *buf, uchar ch)
|
|||
{
|
||||
error_t rc = EOK;
|
||||
|
||||
// Implements playback / scrolling up when line buffering
|
||||
if (buf->flags & (BF_EOF|BF_ERR)) return EENDF;
|
||||
|
||||
// Implements playback / scrolling up when terminal buffering
|
||||
// Note that '\n', '\r' and '\t' can never occur in the buffer
|
||||
// That should change; there should be a flag for it
|
||||
if (buf->flags & BF_LINE) {
|
||||
if (buf->flags & BF_TERM) {
|
||||
|
||||
// Deal with line feeds by filling the rest of the line with spaces
|
||||
// We need a field for choosing a different filler, e.g. '\0'
|
||||
|
@ -93,7 +94,21 @@ error_t bputc(Buffer_t *buf, uchar ch)
|
|||
while (buf->lastLF % 4 > 0) {
|
||||
rc = bputc(buf, ' ');
|
||||
}
|
||||
if (rc > 0) return rc;
|
||||
}
|
||||
|
||||
// Backspace
|
||||
else if (ch == 8) {
|
||||
if (buf->wp > buf->buf) {
|
||||
buf->wp--;
|
||||
rc = bputc(buf, ' ');
|
||||
if (!rc) buf->wp--;
|
||||
}
|
||||
}
|
||||
|
||||
// DEL character
|
||||
else if (ch == 127) {
|
||||
rc = bputc(buf, ' ');
|
||||
if (!rc) buf->wp--;
|
||||
}
|
||||
|
||||
// Just a regular character
|
||||
|
@ -118,7 +133,7 @@ error_t bputc(Buffer_t *buf, uchar ch)
|
|||
}
|
||||
}
|
||||
|
||||
// Not line-buffering
|
||||
// Not a terminal buffer
|
||||
else {
|
||||
if (buf->wp == buf->buf + buf->size) {
|
||||
buf->flags |= BF_EOF;
|
||||
|
@ -127,11 +142,22 @@ error_t bputc(Buffer_t *buf, uchar ch)
|
|||
|
||||
*buf->wp++ = ch;
|
||||
|
||||
if (buf->wp == buf->buf + buf->size && !(buf->flags&BF_FONCLOSE)) {
|
||||
buf->flusher(buf);
|
||||
if (buf->wp == buf->buf + buf->size) {
|
||||
if (!(buf->flags & (BF_LINE|BF_FONCLOSE))) {
|
||||
if (buf->flusher) buf->flusher(buf);
|
||||
}
|
||||
}
|
||||
|
||||
// Line-buffering
|
||||
if (ch == '\n' && buf->flags & BF_LINE) {
|
||||
if (buf->flusher) buf->flusher(buf);
|
||||
}
|
||||
}
|
||||
|
||||
return EOK;
|
||||
if (rc != EOK) {
|
||||
// buf->flags |= BF_ERR;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ error_t BScrollDownBuf(Buffer_t *buf)
|
|||
assert(buf && buf->initDone == INITOK);
|
||||
|
||||
if (!buf) return EINVAL;
|
||||
if (!(buf->flags & BF_TERM)) return EBADF;
|
||||
if (buf->flags & (BF_EOF|BF_ERR)) return EENDF;
|
||||
if (buf->state != BS_RDWR && buf->state != BS_WRONLY) {
|
||||
return EBADF;
|
||||
|
|
|
@ -26,13 +26,25 @@
|
|||
#include <extras/locks.h>
|
||||
#include <extras/malloc.h>
|
||||
|
||||
Buffer_t *BStdOut, *BStdDbg;
|
||||
#include <kernel/base.h>
|
||||
|
||||
Buffer_t *BStdIn, *BStdOut, *BStdDbg;
|
||||
|
||||
// Straightforward functions
|
||||
int BGetFlags(Buffer_t *buf) { return buf->flags; }
|
||||
int BGetState(Buffer_t *buf) { return buf->state; }
|
||||
int BGetLineLen(Buffer_t *buf) { return buf->lineLen; }
|
||||
void BSetLineLen(Buffer_t *buf, int len) { buf->lineLen = len; }
|
||||
|
||||
void BEnableLineBuffering(Buffer_t *buf)
|
||||
{
|
||||
assert(buf && !(buf->flags & BF_TERM));
|
||||
buf->flags |= BF_LINE;
|
||||
}
|
||||
|
||||
void BDisaleLineBuffering(Buffer_t *buf)
|
||||
{
|
||||
assert(buf && !(buf->flags & BF_TERM));
|
||||
buf->flags &= ~BF_LINE;
|
||||
}
|
||||
|
||||
void BLockBuf(Buffer_t *buf)
|
||||
{
|
||||
|
@ -43,8 +55,6 @@ void BLockBuf(Buffer_t *buf)
|
|||
void BUnlockBuf(Buffer_t *buf) { ExReleaseLock(&buf->lock); }
|
||||
bool BTrylockBuf(Buffer_t *buf) { return ExAttemptLock(&buf->lock); }
|
||||
|
||||
void BFlushOnClose(Buffer_t *buf) { buf->flags |= BF_FONCLOSE; }
|
||||
|
||||
//
|
||||
// Closes a buffer, not flushing unless the proper flag is set
|
||||
//
|
||||
|
@ -129,16 +139,16 @@ error_t BOpenPureBufEx(Buffer_t **pbuf, char *source, int mode, size_t size,
|
|||
}
|
||||
|
||||
//
|
||||
// Creates a line buffer of (nLines + pbCount*nLines) lines each
|
||||
// Creates a terminal buffer of (nLines + pbCount*nLines) lines each
|
||||
// of lineLen length (pb = playback buffer, for scrolling up)
|
||||
//
|
||||
error_t BOpenLineBuf(Buffer_t **pbuf, int mode,
|
||||
error_t BOpenTermBuf(Buffer_t **pbuf, int mode,
|
||||
int lineLen, int nLines, int pbCount)
|
||||
{
|
||||
return BOpenLineBufEx(pbuf, NULL, mode, lineLen, nLines, pbCount, NULL);
|
||||
return BOpenTermBufEx(pbuf, NULL, mode, lineLen, nLines, pbCount, NULL);
|
||||
}
|
||||
|
||||
error_t BOpenLineBufEx(Buffer_t **pbuf, char *source, int mode,
|
||||
error_t BOpenTermBufEx(Buffer_t **pbuf, char *source, int mode,
|
||||
int lineLen, int nLines, int pbCount, BFlusher_t flusher)
|
||||
{
|
||||
error_t rc;
|
||||
|
@ -152,7 +162,7 @@ error_t BOpenLineBufEx(Buffer_t **pbuf, char *source, int mode,
|
|||
(*pbuf)->lastLF = 0;
|
||||
(*pbuf)->nLines = nLines;
|
||||
(*pbuf)->lineLen = lineLen;
|
||||
(*pbuf)->flags |= BF_LINE;
|
||||
(*pbuf)->flags |= BF_TERM;
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include <kalbase.h>
|
||||
#include <extras/malloc.h>
|
||||
|
||||
#include<kernel/heap.h>
|
||||
|
||||
/* DO NOT compile with strict aliasing on */
|
||||
|
||||
//------------------------------------------//
|
||||
|
@ -178,7 +180,7 @@ void *memcpy(void *restrict dst, const void *restrict src, size_t bytes)
|
|||
const ulong *usrc = (const ulong *)src;
|
||||
ulong *udst = (ulong *)dst;
|
||||
|
||||
assert("Don't use this, use memmove()");
|
||||
assert(!"Don't use this, use memmove()");
|
||||
assert((dst + bytes < src || src + bytes < dst) && "memcpy() overlap; use memmove()");
|
||||
|
||||
if unlikely (bytes == 0) return dst;
|
||||
|
|
|
@ -22,11 +22,20 @@
|
|||
// along with OS/K. If not, see <https://www.gnu.org/licenses/>. //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
//
|
||||
// TODO integer modifiers
|
||||
//
|
||||
#include <extras/buf.h>
|
||||
|
||||
#include <kalbase.h>
|
||||
//
|
||||
// XXX
|
||||
// For now vsnprintf won't support n > 4096
|
||||
// vsnprintf() is implemented using the libbuf, which
|
||||
// does not support dynamically sized buffers (yet)
|
||||
// (because we need realloc() for that, and we don't have it yet)
|
||||
// So for now we have to create a buffer of size n which is allocated
|
||||
// hard, with no paging etc.
|
||||
// Once libbuf is supports dynamic buffers, the only changes necessary
|
||||
// will be to change the value below to and add a line to vsnprintf()
|
||||
//
|
||||
#define VSNPRINTF_MAX 512
|
||||
|
||||
//
|
||||
// Format str according to fmt using ellipsed arguments
|
||||
|
@ -36,8 +45,10 @@ size_t sprintf(char *str, const char *fmt, ...)
|
|||
int ret;
|
||||
va_list ap;
|
||||
|
||||
assert(!"sprintf() is deprecated, used snprintf() for more safety");
|
||||
|
||||
va_start(ap, fmt);
|
||||
ret = vsnprintf(str, SIZE_T_MAX, fmt, ap);
|
||||
ret = vsnprintf(str, VSNPRINTF_MAX, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return ret;
|
||||
|
@ -45,7 +56,7 @@ size_t sprintf(char *str, const char *fmt, ...)
|
|||
|
||||
size_t vsprintf(char *str, const char *fmt, va_list ap)
|
||||
{
|
||||
return vsnprintf(str, SIZE_T_MAX, fmt, ap);
|
||||
return vsnprintf(str, VSNPRINTF_MAX, fmt, ap);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -64,6 +75,57 @@ size_t snprintf(char *str, size_t n, const char *fmt, ...)
|
|||
return ret;
|
||||
}
|
||||
|
||||
__GET_GETRIP();
|
||||
size_t vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
|
||||
{
|
||||
size_t ret;
|
||||
error_t rc;
|
||||
Buffer_t *buf;
|
||||
|
||||
assert(str && fmt);
|
||||
|
||||
if (n == 0) return 0;
|
||||
if (n > VSNPRINTF_MAX) {
|
||||
assert(!"Not yet...");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// n-1 to leave place for the '\0'
|
||||
if (BOpenPureBuf(&buf, BS_WRONLY, n-1) != EOK) {
|
||||
goto fail;
|
||||
}
|
||||
rc = vbprintf(buf, fmt, ap);
|
||||
|
||||
// We don't mind EOFs, just just return how much was successfully written
|
||||
if (rc != EOK && !(rc == EENDF && !(buf->flags & BF_EOF))) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = (size_t)buf->wp - (size_t)buf->buf;
|
||||
|
||||
if (ret > 0) {
|
||||
// To be changed to memcpy()
|
||||
memmove(str, (char *)buf->buf, ret);
|
||||
}
|
||||
|
||||
str[ret++] = 0;
|
||||
assert(ret <= n);
|
||||
//109e38 101c63
|
||||
|
||||
BCloseBuf(buf);
|
||||
return ret;
|
||||
|
||||
fail:
|
||||
assert(!"vsnprintf() failure");
|
||||
*str = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Old code
|
||||
//
|
||||
#if 0
|
||||
|
||||
// Size of the buffer is for convertions
|
||||
#define CONVBUF 64
|
||||
|
||||
|
@ -242,3 +304,5 @@ size_t vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
|
|||
return ret + 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in New Issue