/*
* Original:
*
* Patrick Powell Tue Apr 11 09:48:21 PDT 1995
* A bombproof version of doprnt (dopr) included.
* Sigh. This sort of thing is always nasty do deal with. Note that
* the version here does not include floating point...
*
* plp_snprintf() is used instead of sprintf() as it does limit checks
* for string length. This covers a nasty loophole.
*
* The other functions are there to prevent NULL pointers from
* causing nast effects.
*
* Modified by:
*
* Christopher D. Granz for use with Sapphire on systems that don't
* normally implement snprintf() and vsnprintf(). Read the file
* "License" for copyright information on this code.
*/
#ifndef _sysBSD
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
#include <sys/types.h>
#include "sapphire.h"
/*
* Prototypes
*/
static void _doprintf ( char *, char *, va_list );
static void _fmtstr ( char *, bool, int );
static void _fmtnum ( long, int, bool, bool, int, int );
static void _outstr ( char * );
static void _outch ( int );
/*
* Globals
*/
static char * pOutput;
static char * pEnd;
/*
* Functions
*/
int vsnprintf( char *pBuf, size_t sSize, char *pFormat, va_list vlArgs )
{
*pBuf = '\0';
pEnd = ( pBuf + sSize - 1 );
_doprintf( pBuf, pFormat, vlArgs );
if ( sSize > 0 )
*pEnd = '\0';
return ( strlen( pBuf ) );
}
int snprintf ( char *pBuf, size_t sSize, char *pFormat, ... )
{
va_list vlArgs;
int i;
va_start( vlArgs, pFormat );
i = vsnprintf ( pBuf, sSize, pFormat, vlArgs );
va_end( vlArgs );
return ( i );
}
/*
* Poor man's version of doprintf().
*/
static void _doprintf( char *pBuf, char *pFormat, va_list vlArgs )
{
char *pStr;
int i;
int iLen;
int iPad;
long l;
bool bLong = FALSE;
bool bJust;
pOutput = pBuf;
while ( ( i = *pFormat++ ) )
{
switch ( i )
{
case '%':
bJust = FALSE;
iLen = 0;
iPad = '\0';
next_ch:
i = *pFormat++;
switch ( i )
{
case 0 : _outstr( "**END OF FORMAT**" ); return;
case '-': bJust = TRUE; goto next_ch;
case '0':
if ( iLen == 0 )
iPad = '0';
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
iLen = ( ( iLen * 10 ) + i - '0' );
goto next_ch;
case 'l': bLong = TRUE; goto next_ch;
case 'u':
case 'U':
if ( bLong != FALSE )
l = va_arg( vlArgs, long );
else
l = va_arg( vlArgs, int );
_fmtnum( l, 10, FALSE, bJust, iLen, iPad );
break;
case 'd':
case 'D':
if ( bLong != FALSE )
l = va_arg( vlArgs, long );
else
l = va_arg( vlArgs, int );
_fmtnum( l, 10, TRUE, bJust, iLen, iPad );
break;
case 'o':
case 'O':
if ( bLong != FALSE )
l = va_arg( vlArgs, long );
else
l = va_arg( vlArgs, int );
_fmtnum( l, 8, FALSE, bJust, iLen, iPad );
break;
case 'x':
if ( bLong != FALSE )
l = va_arg( vlArgs, long );
else
l = va_arg( vlArgs, int );
_fmtnum( l, 16, FALSE, bJust, iLen, iPad );
break;
case 'X':
if ( bLong != FALSE )
l = va_arg( vlArgs, long );
else
l = va_arg( vlArgs, int );
_fmtnum( l, -16, FALSE, bJust, iLen, iPad );
break;
case 's':
pStr = va_arg( vlArgs, char * );
_fmtstr( pStr, bJust, iLen );
break;
case 'c':
i = va_arg( vlArgs, int );
_outch( i );
break;
case '%': _outch( i ); continue;
default : _outstr( "???????" );
}
bLong = FALSE;
break;
default : _outch( i ); break;
}
}
*pOutput = '\0';
}
static void _fmtstr( char *pStr, bool bJust, int iLen )
{
int iPad, iStr;
if ( pStr == NULL )
pStr = "<NULL>";
for ( iStr = 0; pStr[iStr] != '\0'; iStr++ );
iPad = ( iLen - iStr );
if ( iPad < 0 )
iPad = 0;
else if ( bJust != FALSE )
iPad = -iPad;
while ( iPad-- > 0 )
_outch( ' ' );
_outstr( pStr );
while( iPad++ < 0 )
_outch( ' ' );
}
static void _fmtnum( long l, int iBase, bool bDoSign, bool bJust,
int iLen, int iPad )
{
char cBuf[32];
unsigned long ul;
int iSign = '\0';
int i = 0;
int iPadLen = 0;
bool bCaps = 0;
ul = (unsigned long) l;
if ( bDoSign != FALSE )
{
if ( l < 0 )
{
iSign = '-';
ul = (unsigned long) -l;
}
}
if ( iBase < 0 )
{
bCaps = 1;
iBase = -iBase;
}
do
{
cBuf[i++] = ( bCaps != FALSE ? "0123456789ABCDEF"
: "0123456789abcdef" )[ul % (unsigned int) iBase];
ul = ( ul / (unsigned int) iBase );
}
while ( ul != 0 );
cBuf[i] = 0;
iPadLen = ( iLen - i );
if ( iPadLen < 0 )
iPadLen = 0;
if ( bJust != FALSE )
iPadLen = -iPadLen;
if ( iPad != 0 && iPadLen > 0 )
{
if ( iSign != '\0' )
{
_outch( iSign );
iPadLen--;
iSign = '\0';
}
while ( iPadLen-- > 0 )
_outch( iPad );
}
while ( iPadLen-- > 0 )
_outch( ' ' );
if ( iSign != '\0' )
_outch( iSign );
while ( i > 0 )
_outch( cBuf[--i] );
while ( iPadLen++ < 0 )
_outch( ' ' );
}
static void _outstr( char *pStr )
{
while ( *pStr != '\0' )
_outch( *pStr++ );
}
static void _outch( int i )
{
/* if ( iscntrl( i ) && i != '\n' && i != '\t' )
{
i = ( '@' + ( i & 0x1F ) );
if ( pEnd == '\0' || pOutput < pEnd )
*pOutput++ = '^';
} */
if ( pEnd == '\0' || pOutput < pEnd )
*pOutput++ = i;
}
#endif