/
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/
/*
 * Copyright (C) 1995-1997 Christopher D. Granz
 *
 * This header may not be removed.
 *
 * Refer to the file "License" included in this package for further
 * information and before using any of the following.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>

#include "sapphire.h"


/*
 * Functions
 */
static int _compar( const void *p1, const void *p2 )
{
    char *pStr1 = *( (char **) p1 );
    char *pStr2 = *( (char **) p2 );
    char c1;
    char c2;
    int iResult = 0;
    int i;

    for ( i = 0; pStr1[i] != '\0' && pStr2[i] != '\0'; i++ )
    {
        c1      = UPPER( pStr1[i] );
        c2      = UPPER( pStr2[i] );

        if ( ( iResult = ( c1 > c2 ? 1 : ( c1 < c2 ? -1 : 0 ) ) ) )
            break;
    }

    return ( iResult );
}


/*
 * Performs an alphabetacal sort on an array of strings (char pointers.)
 */
char **asort( char **ppSort, int iNumEle )
{
    if ( iNumEle > 0 )
        qsort( ppSort, iNumEle, sizeof( char * ), &_compar );

    return ( ppSort );
}


char *sone_arg( char *pList, char *pArg )
{
    static char cOutput[MAX_STRING];
    int i, iPos, iOPos;

    i                    = 0;
    iPos                 = 0;
    iOPos                = 0;

    while ( isspace( pList[iPos] ) != 0 )
        iPos++;

    do
    {
        if ( pList[iPos] == '\0' || i >= ( MAX_INPUT - 1 ) )
            break;

        pArg[i++]        = pList[iPos++];
    }
    while ( isspace( pList[iPos] ) == 0 );

    pArg[i]              = '\0';

    while ( isspace( pList[iPos] ) != 0 )
        iPos++;

    while ( pList[iPos] != '\0' && iOPos < ( MAX_INPUT - 1 ) )
        cOutput[iOPos++] = pList[iPos++];

    cOutput[iOPos]       = '\0';

    return ( cOutput );
}


/*
 * Get the first word from a list.
 */
char *one_arg( char *pList, char *pArg )
{
    char *pOutput        = new_buffer( );
    int i, iPos, iOPos;

    i                    = 0;
    iPos                 = 0;
    iOPos                = 0;

    while ( isspace( pList[iPos] ) != 0 )
        iPos++;

    do
    {
        if ( pList[iPos] == '\0' || i >= ( MAX_INPUT - 1 ) )
            break;

        pArg[i++]        = pList[iPos++];
    }
    while ( isspace( pList[iPos] ) == 0 );

    pArg[i]              = '\0';

    while ( isspace( pList[iPos] ) != 0 )
        iPos++;

    while ( pList[iPos] != '\0' && iOPos < ( MAX_INPUT - 1 ) )
        pOutput[iOPos++] = pList[iPos++];

    pOutput[iOPos]       = '\0';

    return ( pOutput );
}


char *one_arg_2( char *pList, char *pArg )
{
    int i, iPos, iOPos;

    i                    = 0;
    iPos                 = 0;
    iOPos                = 0;

    while ( isspace( pList[iPos] ) != 0 )
        iPos++;

    do
    {
        if ( pList[iPos] == '\0' || i >= ( MAX_INPUT - 1 ) )
            break;

        pArg[i++]        = pList[iPos++];
    }
    while ( isspace( pList[iPos] ) == 0 );

    pArg[i]              = '\0';

    while ( isspace( pList[iPos] ) != 0 )
        iPos++;

    return ( &pList[iPos] );
}


char *sedit_str( char *pList, char *pStr, char c1, char *p1 )
{
    static char cOutput[MAX_STRING];
    int i, i2, iPos = 0;
    bool b;

    while ( isspace( pList[iPos] ) )
        iPos++;

    if ( pList[iPos] == c1 )
        iPos++;

    while ( isspace( pList[iPos] ) )
        iPos++;

    for ( i = 0; ; i++, iPos++ )
    {
        if ( i >= MAX_STRING )
            goto warning;

        for ( b = FALSE, i2 = 0; p1[i2] != '\0'; i2++ )
        {
            if ( pList[iPos] == p1[i2] )
            {
                b = TRUE;
                break;
            }
        }

        if ( b == TRUE || pList[iPos] == '\0' )
            break;

        pStr[i]    = pList[iPos];
    }

    pStr[i]        = '\0';

    while ( isspace( pList[iPos] ) )
        iPos++;

    for ( i = 0; ; i++, iPos++ )
    {
        if ( i >= MAX_STRING )
            goto warning;

        if ( pList[iPos] == '\0' )
            break;

        cOutput[i] = pList[iPos];
    }

    cOutput[i]     = '\0';
    return ( cOutput );

warning:
    pStr[0]        = '\0';
    wcwarning( "Parse string: String too long." );
    return ( EMPTY_STRING );
}


/*
 * Copys pList into pStr until the character is equal to one of the
 * characters in p1.  If the first character is c1, it will be skiped.
 * Returns what is left on pList (including the terminating character).
 * Basicly this is more complex version of one_arg().
 */
char *edit_str( char *pList, char *pStr, char c1, char *p1 )
{
    char *pOutput   = new_buffer( );
    int i, i2, iPos = 0;
    bool b;

    while ( isspace( pList[iPos] ) )
        iPos++;

    if ( pList[iPos] == c1 )
        iPos++;

    while ( isspace( pList[iPos] ) )
        iPos++;

    for ( i = 0; ; i++, iPos++ )
    {
        if ( i >= MAX_STRING )
            goto warning;

        for ( b = FALSE, i2 = 0; p1[i2] != '\0'; i2++ )
        {
            if ( pList[iPos] == p1[i2] )
            {
                b = TRUE;
                break;
            }
        }

        if ( b == TRUE || pList[iPos] == '\0' )
            break;

        pStr[i]    = pList[iPos];
    }

    pStr[i]        = '\0';

    while ( isspace( pList[iPos] ) )
        iPos++;

    for ( i = 0; ; i++, iPos++ )
    {
        if ( i >= MAX_STRING )
            goto warning;

        if ( pList[iPos] == '\0' )
            break;

        pOutput[i] = pList[iPos];
    }

    pOutput[i]     = '\0';
    return ( pOutput );

warning:
    pStr[0]        = '\0';
    wcwarning( "Parse string: String too long." );
    return ( EMPTY_STRING );
}


char *edit_str_2( char *pList, char *pStr, char c1, char *p1 )
{
    int i, i2, iPos = 0;
    bool b;

    while ( isspace( pList[iPos] ) )
        iPos++;

    if ( pList[iPos] == c1 )
        iPos++;

    while ( isspace( pList[iPos] ) )
        iPos++;

    for ( i = 0; ; i++, iPos++ )
    {
        if ( i >= MAX_STRING )
            goto warning;

        for ( b = FALSE, i2 = 0; p1[i2] != '\0'; i2++ )
        {
            if ( pList[iPos] == p1[i2] )
            {
                b = TRUE;
                break;
            }
        }

        if ( b == TRUE || pList[iPos] == '\0' )
            break;

        pStr[i]    = pList[iPos];
    }

    pStr[i]        = '\0';

    while ( isspace( pList[iPos] ) )
        iPos++;

    return ( &pList[iPos] );

warning:
    pStr[0]        = '\0';
    wcwarning( "Parse string: String too long." );
    return ( EMPTY_STRING );
}


char *sedit_str_plus( char *pList, char *pStr, char c1, char c2 )
{
    static char cOutput[MAX_STRING];
    char c;
    char cQuote     = '\0';
    int i, iPos     = 0;
    int iCount      = 0;

    while ( isspace( pList[iPos] ) )
        iPos++;

    if ( pList[iPos] == c1 )
    {
        iCount++;
        iPos++;
    }

    for ( i = 0; ; i++, iPos++ )
    {
        if ( i >= MAX_STRING )
            goto warning;

        c                     = pList[iPos];

        if ( c == '\0' )
            break;

        switch ( c )
        {
          case '"' :
              if ( cQuote == '\0' )
                  cQuote    = '"';
              else if ( cQuote != '\'' )
                  cQuote    = '\0';

              break;

          case '\'':
              if ( cQuote == '\0' )
                  cQuote    = '\'';
              else if ( cQuote != '"' )
                  cQuote    = '\0';

              break;

          case '\n':
          case '\r':
          case '\t':
              if ( cQuote != '\0' )
                  c           = ' ';

              break;

          case '\\':
              if ( cQuote != '\0' )
              {
                  iPos++;

                  switch ( ( c = pList[iPos] ) )
                  {
                    case '\0':
                    case '\\':
                    case '"' :
                    case '\'':
                        break;

                    default  :
                        c = '\\';
                        break;
                  }
              }

          default  :
              break;
        }

        if ( cQuote == '\0' )
        {
            if ( c == c2 )
            {
                if ( iCount != 0 )
                {
                    iCount--;

                    if ( iCount == 0 )
                        break;
                }
                else
                    break;
            }
            else if ( c == c1 )
                iCount++;
        }

        pStr[i]    = c;
    }

    pStr[i]        = '\0';

    for ( i = 0; ; i++, iPos++ )
    {
        if ( i >= MAX_STRING )
            goto warning;

        if ( pList[iPos] == '\0' )
            break;

        cOutput[i] = pList[iPos];
    }

    cOutput[i]     = '\0';
    return ( cOutput );

warning:
    pStr[0]        = '\0';
    wcwarning( "Parse string: String too long." );
    return ( EMPTY_STRING );
}


/*
 * Closely related to edit_str().  Copys pList into pStr from c1 to c2.
 * Will skip nested forms of c1 and c2.  Example:
 *
 * char cBuf[100];
 * char *pReturnStr;
 * char *pStr = "[Parse [nested] test] ... garbage ...";
 *
 * pReturnStr = edit_str_plus( pStr, cBuf, '[', ']' );
 *
 * The result would be that pReturnStr is equal to "... garbage ..." and
 * cBuf is equal to "[Parse [nested] test]".  pStr would remain unchanged.
 */
char *edit_str_plus( char *pList, char *pStr, char c1, char c2 )
{
    char *pOutput   = new_buffer( );
    char c;
    char cQuote     = '\0';
    int i, iPos     = 0;
    int iCount      = 0;

    while ( isspace( pList[iPos] ) )
        iPos++;

    if ( pList[iPos] == c1 )
    {
        iCount++;
        iPos++;
    }

    for ( i = 0; ; i++, iPos++ )
    {
        if ( i >= MAX_STRING )
            goto warning;

        c                     = pList[iPos];

        if ( c == '\0' )
            break;

        switch ( c )
        {
          case '"' :
              if ( cQuote == '\0' )
                  cQuote    = '"';
              else if ( cQuote != '\'' )
                  cQuote    = '\0';

              break;

          case '\'':
              if ( cQuote == '\0' )
                  cQuote    = '\'';
              else if ( cQuote != '"' )
                  cQuote    = '\0';

              break;

          case '\n':
          case '\r':
          case '\t':
              if ( cQuote != '\0' )
                  c           = ' ';

              break;

          case '\\':
              if ( cQuote != '\0' )
              {
                  iPos++;

                  switch ( ( c = pList[iPos] ) )
                  {
                    case '\0':
                    case '\\':
                    case '"' :
                    case '\'':
                        break;

                    default  :
                        c = '\\';
                        break;
                  }
              }

          default  :
              break;
        }

        if ( cQuote == '\0' )
        {
            if ( c == c2 )
            {
                if ( iCount != 0 )
                {
                    iCount--;

                    if ( iCount == 0 )
                        break;
                }
                else
                    break;
            }
            else if ( c == c1 )
                iCount++;
        }

        pStr[i]    = c;
    }

    pStr[i]        = '\0';

    for ( i = 0; ; i++, iPos++ )
    {
        if ( i >= MAX_STRING )
            goto warning;

        if ( pList[iPos] == '\0' )
            break;

        pOutput[i] = pList[iPos];
    }

    pOutput[i]     = '\0';
    return ( pOutput );

warning:
    pStr[0]        = '\0';
    wcwarning( "Parse string: String too long." );
    return ( EMPTY_STRING );
}


char *edit_str_plus_2( char *pList, char *pStr, char c1, char c2 )
{
    char c;
    char cQuote     = '\0';
    int i, iPos     = 0;
    int iCount      = 0;

    while ( isspace( pList[iPos] ) )
        iPos++;

    if ( pList[iPos] == c1 )
    {
        iCount++;
        iPos++;
    }

    for ( i = 0; ; i++, iPos++ )
    {
        if ( i >= MAX_STRING )
            goto warning;

        c                     = pList[iPos];

        if ( c == '\0' )
            break;

        switch ( c )
        {
          case '"' :
              if ( cQuote == '\0' )
                  cQuote    = '"';
              else if ( cQuote != '\'' )
                  cQuote    = '\0';

              break;

          case '\'':
              if ( cQuote == '\0' )
                  cQuote    = '\'';
              else if ( cQuote != '"' )
                  cQuote    = '\0';

              break;

          case '\n':
          case '\r':
          case '\t':
              if ( cQuote != '\0' )
                  c           = ' ';

              break;

          case '\\':
              if ( cQuote != '\0' )
              {
                  iPos++;

                  switch ( ( c = pList[iPos] ) )
                  {
                    case '\0':
                    case '\\':
                    case '"' :
                    case '\'':
                        break;

                    default  :
                        c = '\\';
                        break;
                  }
              }

          default  :
              break;
        }

        if ( cQuote == '\0' )
        {
            if ( c == c2 )
            {
                if ( iCount != 0 )
                {
                    iCount--;

                    if ( iCount == 0 )
                        break;
                }
                else
                    break;
            }
            else if ( c == c1 )
                iCount++;
        }

        pStr[i]    = c;
    }

    pStr[i]        = '\0';

    return ( &pList[iPos] );

warning:
    pStr[0]        = '\0';
    wcwarning( "Parse string: String too long." );
    return ( EMPTY_STRING );
}


char *smake_string( char *pList, char *pStr )
{
    static char cOutput[MAX_STRING];
    int i;

    while ( isspace( *pList ) )
        pList++;

    if ( *pList != '"' )
    {
        sap_warning( "Parse string: Symbol `\"' not found." );
        return ( EMPTY_STRING );
    }

    if ( *( ++pList ) == '"' )
        return ( EMPTY_STRING );

    for ( i = 0; ; i++, pList++ )
    {
        if ( i >= MAX_STRING )
            goto warning;

        if ( *pList == '\\' )
        {
            switch ( *( ++pList ) )
            {
              case '\\': pStr[i] = '\\'; break;
              case '"' : pStr[i] = '"';  break;
              case 'n' : pStr[i] = '\n'; break;
              case 'r' : pStr[i] = '\r'; break;
              case 't' : pStr[i] = '\t'; break;
              case 'a' : pStr[i] = '\a'; break;
              case '\0':
                  sap_warning( "Parse string: Incomplete escape." );
                  break;

              default  :
                  sap_warning( "Parse string: Unknown escape '\\%c'.",
                    *pList );
                  break;
            }
        }
        else if ( *pList != '\n' && *pList != '\r' && *pList != '\t'
          && *pList != '"' )
            pStr[i] = *pList;
        else
            i--;

        if ( *pList == '\0' )
        {
            sap_warning( "Parse string: Symbol `\"' not found." );
            break;
        }

        if ( *pList == '"' )
            break;
    }

    pStr[i + 1]     = '\0';

    for ( i = 0; *pList != '\0'; i++ )
    {
        if ( i >= MAX_STRING )
            goto warning;

        cOutput[i]  = *pList++;
    }

    cOutput[i]      = '\0';
    return ( cOutput );

warning:
    pStr[0]         = '\0';
    sap_warning( "Parse string: String too long." );
    return ( EMPTY_STRING );
}


char *make_string( char *pList, char *pStr )
{
    char *pOutput = new_buffer( );
    int i;

    while ( isspace( *pList ) )
        pList++;

    if ( *pList != '"' )
    {
        sap_warning( "Parse string: Symbol `\"' not found." );
        return ( EMPTY_STRING );
    }

    if ( *( ++pList ) == '"' )
        return ( EMPTY_STRING );

    for ( i = 0; ; i++, pList++ )
    {
        if ( i >= MAX_STRING )
            goto warning;

        if ( *pList == '\\' )
        {
            switch ( *( ++pList ) )
            {
              case '\\': pStr[i] = '\\'; break;
              case '"' : pStr[i] = '"';  break;
              case 'n' : pStr[i] = '\n'; break;
              case 'r' : pStr[i] = '\r'; break;
              case 't' : pStr[i] = '\t'; break;
              case 'a' : pStr[i] = '\a'; break;
              case '\0':
                  sap_warning( "Parse string: Incomplete escape." );
                  break;

              default  :
                  sap_warning( "Parse string: Unknown escape '\\%c'.",
                    *pList );
                  break;
            }
        }
        else if ( *pList != '\n' && *pList != '\r' && *pList != '\t'
          && *pList != '"' )
            pStr[i] = *pList;
        else
            i--;

        if ( *pList == '\0' )
        {
            sap_warning( "Parse string: Symbol `\"' not found." );
            break;
        }

        if ( *pList == '"' )
            break;
    }

    pStr[i + 1]     = '\0';

    for ( i = 0; *pList != '\0'; i++ )
    {
        if ( i >= MAX_STRING )
            goto warning;

        pOutput[i]  = *pList++;
    }

    pOutput[i]      = '\0';
    return ( pOutput );

warning:
    pStr[0]         = '\0';
    sap_warning( "Parse string: String too long." );
    return ( EMPTY_STRING );
}


char *make_string_2( char *pList, char *pStr )
{
    int i;

    while ( isspace( *pList ) )
        pList++;

    if ( *pList != '"' )
    {
        sap_warning( "Parse string: Symbol `\"' not found." );
        return ( EMPTY_STRING );
    }

    if ( *( ++pList ) == '"' )
        return ( EMPTY_STRING );

    for ( i = 0; ; i++, pList++ )
    {
        if ( i >= MAX_STRING )
            goto warning;

        if ( *pList == '\\' )
        {
            switch ( *( ++pList ) )
            {
              case '\\': pStr[i] = '\\'; break;
              case '"' : pStr[i] = '"';  break;
              case 'n' : pStr[i] = '\n'; break;
              case 'r' : pStr[i] = '\r'; break;
              case 't' : pStr[i] = '\t'; break;
              case 'a' : pStr[i] = '\a'; break;
              case '\0':
                  sap_warning( "Parse string: Incomplete escape." );
                  break;

              default  :
                  sap_warning( "Parse string: Unknown escape '\\%c'.",
                    *pList );
                  break;
            }
        }
        else if ( *pList != '\n' && *pList != '\r' && *pList != '\t'
          && *pList != '"' )
            pStr[i] = *pList;
        else
            i--;

        if ( *pList == '\0' )
        {
            sap_warning( "Parse string: Symbol `\"' not found." );
            break;
        }

        if ( *pList == '"' )
            break;
    }

    pStr[i + 1]     = '\0';

    return ( pList );

warning:
    pStr[0]         = '\0';
    sap_warning( "Parse string: String too long." );
    return ( EMPTY_STRING );
}


/*
 * Flips a string.
 */
char *flip_string( char *pStr )
{
    char *pOutput  = new_buffer( );
    int i, iEnd    = ( strlen( pStr ) - 1 );

    for ( i = 0; iEnd < 0; i++, iEnd-- )
        pOutput[i] = pStr[iEnd];

    pOutput[i]     = '\0';

    return ( pOutput );
}


/*
 * Returns the next character in a string.
 */
char next_char( char *pStr )
{
    int iPos = 0;

    while ( isspace( pStr[iPos] ) )
        iPos++;

    return ( pStr[iPos] );
}


/*
 * Removes the first character of a string and copys the rest into
 * a new buffer.
 */
char *remove_char( char *pStr )
{
    char *pOutput = new_buffer( );
    int i, iPos   = 0;

    while ( isspace( pStr[iPos] ) )
        iPos++;

    if ( pStr[iPos] == '\0' )
        return ( EMPTY_STRING );

    for ( i = 0, iPos++; pStr[iPos] != '\0'; i++, iPos++ )
    {
        if ( i >= MAX_STRING )
        {
            wcwarning( "Parse string: String too long." );
            return ( EMPTY_STRING );
        }

        pOutput[i] = pStr[iPos];
    }

    pOutput[i]     = '\0';
    return ( pOutput );
}


char *remove_char_2( char *pStr )
{
    int i = 0;

    while ( isspace( pStr[i] ) )
        i++;

    if ( pStr[i] == '\0' )
        return ( &pStr[i] );

    return ( &pStr[++i] );
}


/*
 * Removes the spaces from the beginning and the end
 * of a string.
 */
char *remove_spaces( char *pStr )
{
    char *pOutput   = new_buffer( );
    char cBuf[MAX_STRING];
    int i, i2, iPos = 0;

    while ( isspace( pStr[iPos] ) )
        iPos++;

    for ( i = 0; pStr[iPos] != '\0'; i++, iPos++ )
    {
        if ( i >= MAX_STRING )
            goto warning;

        cBuf[i]    = pStr[iPos];
    }

    cBuf[i]        = '\0';

    for ( i2 = ( strlen( cBuf ) - 1 ); isspace( cBuf[i2] ); i2-- );

    for ( i = 0; i <= i2; i++ )
    {
        if ( i >= MAX_STRING )
            goto warning;

        pOutput[i] = cBuf[i];
    }

    pOutput[i]     = '\0';
    return ( pOutput );

warning:
    wcwarning( "Parse string: String too long." );
    return ( EMPTY_STRING );
}


/*
 * Removes all newlines/carriage returns from a string.
 */
char *remove_nls( char *pStr )
{
    char *pOutput = new_buffer( );
    int i;

    for ( i = 0; pStr[i] != '\0'; i++ )
    {
        if ( pStr[i] == '\n' || pStr[i] == '\r' )
            pOutput[i] = ' ';
        else
            pOutput[i] = pStr[i];
    }

    pOutput[i]         = '\0';
    return ( pOutput );
}


char *capit( char *pStr )
{
    char *pOutput = new_buffer( );
    int i;

    for ( i = 0; pStr[i] != '\0'; i++ )
        pOutput[i] = LOWER( pStr[i] );

    pOutput[i]     = '\0';
    pOutput[0]     = UPPER( pOutput[0] );

    return ( pOutput );
}


char *uncapit( char *pStr )
{
    char *pOutput = new_buffer( );
    int i;

    for ( i = 0; pStr[i] != '\0'; i++ )
        pOutput[i] = LOWER( pStr[i] );

    pOutput[i]     = '\0';

    return ( pOutput );
}


char *cap_first( char *pStr )
{
    char *pOutput = new_buffer( );
    int i;

    for ( i = 0; pStr[i] != '\0'; i++ )
        pOutput[i] = pStr[i];

    pOutput[i]     = '\0';
    pOutput[0]     = UPPER( pOutput[0] );

    return ( pOutput );
}


/*
 * End of parse.c
 */