/
Sapphire/bin/
Sapphire/db/
Sapphire/db/OLC_rooms/
Sapphire/db/abi/
Sapphire/db/em_src/
Sapphire/db/helps/
Sapphire/db/helps/emman/ifunc/
Sapphire/db/npcs/Tatt/
Sapphire/db/objects/Tatt/
Sapphire/db/q_data/
Sapphire/db/rooms/Tatt/
Sapphire/doc/
Sapphire/doc/em/
Sapphire/etc/
Sapphire/src/abic/
Sapphire/src/areacon/
Sapphire/src/client/
Sapphire/src/embc/
Sapphire/src/emi/
Sapphire/src/emi/test/
Sapphire/src/include/
Sapphire/src/sapphire/em/
Sapphire/src/tcon/
/*
 * 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