/* * 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