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