Pushing bugs

This commit is contained in:
Julian Barathieu 2019-05-07 22:32:17 +02:00
parent a362655af2
commit 241eeb64cb
17 changed files with 202 additions and 66 deletions

View File

@ -34,15 +34,16 @@
// //
enum enum
{ {
BF_LINE = 1, // Line-buffered BF_TERM = 1, // Terminal buffer
BF_FILE = 1<<1, // Linked to a file BF_LINE = 1<<1, // Line-buffered
BF_BALLOC = 1<<2, // Buffer structure was malloc'd BF_FILE = 1<<2, // Linked to a file
BF_SALLOC = 1<<3, // Internal buffer was malloc'd BF_BALLOC = 1<<3, // Buffer structure was malloc'd
BF_FONCLOSE = 1<<4, // Flush on close BF_SALLOC = 1<<4, // Internal buffer was malloc'd
BF_AUTOSCROLL = 1<<5, // Scroll-down automatically BF_FONCLOSE = 1<<5, // Flush on close
BF_AUTOSCROLL = 1<<6, // Scroll-down automatically
BF_EOF = 1<<6, // End of file reached BF_EOF = 1<<7, // End of file reached
BF_ERR = 1<<7, // An error happened BF_ERR = 1<<8, // An error happened
}; };
// //
@ -61,7 +62,7 @@ enum
typedef struct Buffer_t Buffer_t; 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 // For pure buffers, the flusher is called by bputc() after it fills
// the buffer (unless flush-on-close is enabled) // the buffer (unless flush-on-close is enabled)
// //
@ -90,7 +91,7 @@ struct Buffer_t
BFlusher_t flusher; // See above 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 lastLF; // Characters since beginning of line
int lineLen; // Line length (for line buffers) int lineLen; // Line length (for line buffers)
@ -98,14 +99,16 @@ struct Buffer_t
// size/(lineLen*nLines) - 1 playback buffers // size/(lineLen*nLines) - 1 playback buffers
}; };
extern Buffer_t *BStdOut, *BStdDbg; extern Buffer_t *BStdIn, *BStdOut, *BStdDbg;
error_t BCloseBuf(Buffer_t *); // For pure buffers only
void BFlushOnClose(Buffer_t *); void BEnableLineBuffering(Buffer_t *);
void BDisaleLineBuffering(Buffer_t *);
// For terminal buffers only
error_t BScrollDownBuf(Buffer_t *);
void BEnableAutoScroll(Buffer_t *); void BEnableAutoScroll(Buffer_t *);
void BDisableAutoScroll(Buffer_t *); void BDisableAutoScroll(Buffer_t *);
// //
// Buffer creation functions // Buffer creation functions
// //
@ -116,34 +119,32 @@ void BDisableAutoScroll(Buffer_t *);
// If source==NULL, malloc's the buffer // If source==NULL, malloc's the buffer
// BCloseBuf() handles the de-allocations // BCloseBuf() handles the de-allocations
// //
error_t BCloseBuf(Buffer_t *);
// Creates a pure buffer of a given size // Creates a pure buffer of a given size
error_t BOpenPureBuf(Buffer_t **pbuf, int mode, size_t size); error_t BOpenPureBuf(Buffer_t **pbuf, int mode, size_t size);
error_t BOpenPureBufEx(Buffer_t **, char *source, int mode, size_t, error_t BOpenPureBufEx(Buffer_t **, char *source, int mode, size_t,
BFlusher_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) // 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); 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 lineLen, int nLines, int pbCount, BFlusher_t);
int BGetFlags(Buffer_t *); int BGetFlags(Buffer_t *);
int BGetState(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 BLockBuf(Buffer_t *);
void BUnlockBuf(Buffer_t *); void BUnlockBuf(Buffer_t *);
bool BTrylockBuf(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 // Internal, non-locking functions; don't use unless you
// have a good reason why // have a good reason why
error_t bputc(Buffer_t *buf, uchar ch); error_t bputc(Buffer_t *buf, uchar ch);

View File

@ -170,6 +170,14 @@ noreturn void KeStartPanic(const char *, ...);
#define BUG() XBUG('B') #define BUG() XBUG('B')
#define BUGON(x) if(x)BUG() #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 #endif

View File

@ -32,7 +32,9 @@
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
// Address of the heap // Address of the heap
void *_heap_start; extern void *_heap_start;
extern void *_heap_end;
extern size_t _heap_max;
void MmInitHeap(void); void MmInitHeap(void);

View File

@ -75,22 +75,22 @@ noreturn void BtStartKern(multiboot_info_t *mbInfo, uint mbMagic, void *codeSeg)
// Several inits // Several inits
MmInitHeap(); MmInitHeap();
PsInitSched(); //PsInitSched();
// Interrupts launching // Interrupts launching
IdtSetup(); IdtSetup();
KeEnableIRQs(); KeEnableIRQs();
// Drivers enabling // Drivers enabling
IoEnableRtc(); IoEnableRtc();
IoEnableKeyb(); IoEnableKeyb();
IoGetRtcTimeChar();
IoPrintRtcTime(); IoPrintRtcTime();
// IoDoStarWars();
IoDoStarWars();
KernLog("Goodbye at %s\n", IoGetRtcTimeChar()); KernLog("Goodbye at %s\n", IoGetRtcTimeChar());
// End this machine's suffering // End this machine's suffering
BStdOut->flusher(BStdOut); BFlushBuf(BStdOut);
KeCrashSystem(); KeCrashSystem();
} }

View File

@ -31,7 +31,7 @@ char ScanCodes[100] = { 0 };
void KeybPrint(char code) void KeybPrint(char code)
{ {
if (code) { if (code) {
bprintf(BStdOut, "%c", ScanCodes[(int)code]); bputc(BStdOut, ScanCodes[(int)code]);
//bprintf(BStdOut, "%x ", code); //bprintf(BStdOut, "%x ", code);
BStdOut->flusher(BStdOut); BStdOut->flusher(BStdOut);
} }
@ -51,7 +51,8 @@ void ScanCodesInit(void)
ScanCodes[0x0B] = '0'; ScanCodes[0x0B] = '0';
ScanCodes[0x0C] = ' '; ScanCodes[0x0C] = ' ';
ScanCodes[0x0D] = '+'; ScanCodes[0x0D] = '+';
ScanCodes[0x0E] = ' '; ScanCodes[0x0E] = 0x8;
ScanCodes[0x0F] = '\t';
ScanCodes[0x10] = 'a'; ScanCodes[0x10] = 'a';
ScanCodes[0x11] = 'z'; ScanCodes[0x11] = 'z';
@ -113,13 +114,29 @@ void KeybHandler(ISRFrame_t *regs)
IoSendEOItoPIC(0x21); 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) void IoEnableKeyb(void)
{ {
ulong flags = KePauseIRQs(); ulong flags = KePauseIRQs();
IdtRegisterIsr(KeybHandler, 0x21); IdtRegisterIsr(KeybHandler, 0x21);
char readedInterruptConfig = IoReadByteFromPort(0x21); char readedInterruptConfig = IoReadByteFromPort(0x21);
IoWriteByteOnPort(0x21, 0xFD & readedInterruptConfig); IoWriteByteOnPort(0x21, 0xFD & readedInterruptConfig);
KeRestoreIRQs(flags); KeRestoreIRQs(flags);
IoEnableNMI(); IoEnableNMI();
ScanCodesInit(); ScanCodesInit();
IoCreateInputBuffer();
} }

View File

@ -164,7 +164,8 @@ void IoPrintRtcTime(void)
char* IoGetRtcTimeChar(void) char* IoGetRtcTimeChar(void)
{ {
Time_t *RtcTime = IoGetRtcTime(); 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->day,
RtcTime->month, RtcTime->month,
RtcTime->year + RtcTime->century*100, RtcTime->year + RtcTime->century*100,

View File

@ -90,7 +90,7 @@ error_t IoInitVGABuffer(void)
BStdOut = &bvgabufstruct; BStdOut = &bvgabufstruct;
BOpenLineBufEx(&BStdOut, BOpenTermBufEx(&BStdOut,
bvgabufsrc, BS_WRONLY, bvgabufsrc, BS_WRONLY,
BtVideoInfo.framebufferWidth, BtVideoInfo.framebufferWidth,
BtVideoInfo.framebufferHeight, BtVideoInfo.framebufferHeight,

View File

@ -26,11 +26,14 @@
#include <kernel/heap.h> #include <kernel/heap.h>
#include <extras/locks.h> #include <extras/locks.h>
// Least address out of the heap // Start address of the heap
static void *_heap_end; void *_heap_start;
// End of the heap
/*static*/ void *_heap_end;
// Maximal value of the heap // Maximal value of the heap
static size_t _heap_max; /*static*/ size_t _heap_max;
// Lock NOT used internally, but used by KalAllocMemory() & co. // Lock NOT used internally, but used by KalAllocMemory() & co.
static Lock_t _heap_lock = ExINITLOCK(KLOCK_SPINLOCK); static Lock_t _heap_lock = ExINITLOCK(KLOCK_SPINLOCK);
@ -114,6 +117,7 @@ error_t MmGrowHeap(size_t req)
assert(req % alignof(QWORD) == 0); assert(req % alignof(QWORD) == 0);
if ((size_t)_heap_end + req > (size_t)_heap_start + _heap_max) { if ((size_t)_heap_end + req > (size_t)_heap_start + _heap_max) {
assert(!"Can't extend heap that much");
return ENOMEM; return ENOMEM;
} }
@ -130,6 +134,7 @@ error_t MmShrinkHeap(size_t req)
assert(req % alignof(QWORD) == 0); assert(req % alignof(QWORD) == 0);
if (req > (size_t)_heap_end - (size_t)_heap_start) { if (req > (size_t)_heap_end - (size_t)_heap_start) {
assert(!"Can't shrink heap that much");
return EADDRINUSE; return EADDRINUSE;
} }

View File

@ -34,7 +34,6 @@ error_t KalAllocMemoryEx(void **ptr, size_t req, int flags, size_t align)
{ {
error_t rc; error_t rc;
size_t brk; size_t brk;
extern void *_heap_start;
if (align == 0) align = M_DEFAULT_ALIGNMENT; if (align == 0) align = M_DEFAULT_ALIGNMENT;

View File

@ -58,7 +58,7 @@ static error_t InitMemoryMap(void)
if ((BtMemoryInfo.upMemory / (MB/KB)) <= MINIMUM_RAM_SIZE) if ((BtMemoryInfo.upMemory / (MB/KB)) <= MINIMUM_RAM_SIZE)
return ENOMEM; return ENOMEM;
// Ok then we can work ------------------------------------------------------ // // Ok then we can work
// the memory map provided by GRUB via the BIOS // the memory map provided by GRUB via the BIOS
currentEntry = (multiboot_memory_map_t*)BtMemoryInfo.mapAddr; currentEntry = (multiboot_memory_map_t*)BtMemoryInfo.mapAddr;

0
kaleid/libbuf/bgetc.c Normal file
View File

View File

@ -392,7 +392,7 @@ error_t vbprintf(Buffer_t *buf, const char *fmt, va_list ap)
// Carry on to next modifier // Carry on to next modifier
} }
// Assert rc for debugging purposes // Assert !rc for debugging purposes
assert(!rc); assert(!rc);
return rc; return rc;

View File

@ -34,7 +34,6 @@ error_t BPutOnBuf(Buffer_t *buf, uchar ch)
assert(buf && buf->initDone == INITOK); assert(buf && buf->initDone == INITOK);
if (!buf) return EINVAL; if (!buf) return EINVAL;
if (buf->flags & (BF_EOF|BF_ERR)) return EENDF;
if (buf->state != BS_RDWR && buf->state != BS_WRONLY) { if (buf->state != BS_RDWR && buf->state != BS_WRONLY) {
return EBADF; return EBADF;
} }
@ -52,10 +51,12 @@ error_t bputc(Buffer_t *buf, uchar ch)
{ {
error_t rc = EOK; 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 // Note that '\n', '\r' and '\t' can never occur in the buffer
// That should change; there should be a flag for it // 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 // 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' // 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) { while (buf->lastLF % 4 > 0) {
rc = bputc(buf, ' '); 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 // Just a regular character
@ -118,7 +133,7 @@ error_t bputc(Buffer_t *buf, uchar ch)
} }
} }
// Not line-buffering // Not a terminal buffer
else { else {
if (buf->wp == buf->buf + buf->size) { if (buf->wp == buf->buf + buf->size) {
buf->flags |= BF_EOF; buf->flags |= BF_EOF;
@ -127,11 +142,22 @@ error_t bputc(Buffer_t *buf, uchar ch)
*buf->wp++ = ch; *buf->wp++ = ch;
if (buf->wp == buf->buf + buf->size && !(buf->flags&BF_FONCLOSE)) { if (buf->wp == buf->buf + buf->size) {
buf->flusher(buf); if (!(buf->flags & (BF_LINE|BF_FONCLOSE))) {
if (buf->flusher) buf->flusher(buf);
} }
} }
return EOK; // Line-buffering
if (ch == '\n' && buf->flags & BF_LINE) {
if (buf->flusher) buf->flusher(buf);
}
}
if (rc != EOK) {
// buf->flags |= BF_ERR;
}
return rc;
} }

View File

@ -34,6 +34,7 @@ error_t BScrollDownBuf(Buffer_t *buf)
assert(buf && buf->initDone == INITOK); assert(buf && buf->initDone == INITOK);
if (!buf) return EINVAL; if (!buf) return EINVAL;
if (!(buf->flags & BF_TERM)) return EBADF;
if (buf->flags & (BF_EOF|BF_ERR)) return EENDF; if (buf->flags & (BF_EOF|BF_ERR)) return EENDF;
if (buf->state != BS_RDWR && buf->state != BS_WRONLY) { if (buf->state != BS_RDWR && buf->state != BS_WRONLY) {
return EBADF; return EBADF;

View File

@ -26,13 +26,25 @@
#include <extras/locks.h> #include <extras/locks.h>
#include <extras/malloc.h> #include <extras/malloc.h>
Buffer_t *BStdOut, *BStdDbg; #include <kernel/base.h>
Buffer_t *BStdIn, *BStdOut, *BStdDbg;
// Straightforward functions // Straightforward functions
int BGetFlags(Buffer_t *buf) { return buf->flags; } int BGetFlags(Buffer_t *buf) { return buf->flags; }
int BGetState(Buffer_t *buf) { return buf->state; } 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) void BLockBuf(Buffer_t *buf)
{ {
@ -43,8 +55,6 @@ void BLockBuf(Buffer_t *buf)
void BUnlockBuf(Buffer_t *buf) { ExReleaseLock(&buf->lock); } void BUnlockBuf(Buffer_t *buf) { ExReleaseLock(&buf->lock); }
bool BTrylockBuf(Buffer_t *buf) { return ExAttemptLock(&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 // 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) // 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) 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) int lineLen, int nLines, int pbCount, BFlusher_t flusher)
{ {
error_t rc; error_t rc;
@ -152,7 +162,7 @@ error_t BOpenLineBufEx(Buffer_t **pbuf, char *source, int mode,
(*pbuf)->lastLF = 0; (*pbuf)->lastLF = 0;
(*pbuf)->nLines = nLines; (*pbuf)->nLines = nLines;
(*pbuf)->lineLen = lineLen; (*pbuf)->lineLen = lineLen;
(*pbuf)->flags |= BF_LINE; (*pbuf)->flags |= BF_TERM;
} }
return rc; return rc;

View File

@ -25,6 +25,8 @@
#include <kalbase.h> #include <kalbase.h>
#include <extras/malloc.h> #include <extras/malloc.h>
#include<kernel/heap.h>
/* DO NOT compile with strict aliasing on */ /* 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; const ulong *usrc = (const ulong *)src;
ulong *udst = (ulong *)dst; 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()"); assert((dst + bytes < src || src + bytes < dst) && "memcpy() overlap; use memmove()");
if unlikely (bytes == 0) return dst; if unlikely (bytes == 0) return dst;

View File

@ -22,11 +22,20 @@
// along with OS/K. If not, see <https://www.gnu.org/licenses/>. // // along with OS/K. If not, see <https://www.gnu.org/licenses/>. //
//----------------------------------------------------------------------------// //----------------------------------------------------------------------------//
// #include <extras/buf.h>
// TODO integer modifiers
//
#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 // Format str according to fmt using ellipsed arguments
@ -36,8 +45,10 @@ size_t sprintf(char *str, const char *fmt, ...)
int ret; int ret;
va_list ap; va_list ap;
assert(!"sprintf() is deprecated, used snprintf() for more safety");
va_start(ap, fmt); va_start(ap, fmt);
ret = vsnprintf(str, SIZE_T_MAX, fmt, ap); ret = vsnprintf(str, VSNPRINTF_MAX, fmt, ap);
va_end(ap); va_end(ap);
return ret; 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) 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; 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 // Size of the buffer is for convertions
#define CONVBUF 64 #define CONVBUF 64
@ -242,3 +304,5 @@ size_t vsnprintf(char *str, size_t n, const char *fmt, va_list ap)
return ret + 1; return ret + 1;
} }
#endif