📄 _pi3expr.cpp
字号:
strncpy( pszBuffer, pMessage, iLen );
iLength -= iLen;
pszBuffer = &(pszBuffer[iLen]);
};
};
PIDBIterator_delete( pIter );
};
return iTotalLen;
}
static int sc_g( Context &tContext, char *pszBuffer, int iLength )
{
int iOn = (int)PIDB_lookup( tContext.tPIHTTP.pConnectionDB, PIDBTYPE_STRING,
KEY_HTTPS_KEYSIZE, 0 );
const char *pString;
int iValueLen;
if ( iOn )
{
pString = "on";
iValueLen = 2;
}
else
{
pString = "off";
iValueLen = 3;
};
int iLen = iValueLen < iLength ? iValueLen : iLength;
if ( iLen>0 )
{
assert( pszBuffer );
strncpy( pszBuffer, pString, iLen );
};
return iValueLen;
}
static int sc_t( Context &tContext, char *pszBuffer, int iLength )
{
(void)tContext;
enum { BUF_SIZE=255 };
char szBuf[BUF_SIZE+1];
PIPlatform_beforeUnsafeBlock();
time_t tT;
time( &tT );
#if 0
struct tm *pTms = gmtime( &tT );
int iValueLen = strftime( szBuf, BUF_SIZE, "%d/%b/%Y:%H:%M:%S +0000", pTms );
#endif
struct tm *pTms = gmtime( &tT );
/*
** Bit of wierd logic here, but were taking into account timezone
** adjustment on new years eve. Hence use of year. The year multiplier
** doesn't matter once its greater than 365 (its only used for
** comparision between gmt and localtime, and they are both multiplyied
** by the same number
*/
int iGmtYearDay = ( pTms->tm_year * 366 ) + pTms->tm_yday;
int iGmtHourMin = ( pTms->tm_hour * 60 ) + pTms->tm_min ;
pTms = localtime( &tT );
int iValueLen = strftime( szBuf, BUF_SIZE, "%d/%b/%Y:%H:%M:%S", pTms );
int iYearDay = ( pTms->tm_year * 366 ) + pTms->tm_yday;
int iHourMin = ( pTms->tm_hour * 60 ) + pTms->tm_min ;
PIPlatform_afterUnsafeBlock();
int iAdjust = ( iHourMin - iGmtHourMin ) ;
if ( iGmtYearDay>iYearDay )
{ iAdjust -= ( 24 * 60 ) ; };
char cSign;
if ( iAdjust > 0 )
{
cSign = '+';
}
else
{
cSign = '-';
iAdjust = -iAdjust;
};
sprintf( &(szBuf[20]), " %c%02d%02d", cSign, iAdjust / 60, iAdjust % 60 );
iValueLen += 6;
int iLen = iValueLen < iLength ? iValueLen : iLength;
if ( iLen>0 )
{
assert( pszBuffer );
strncpy( pszBuffer, szBuf, iLen );
};
return iValueLen;
}
static int sc_T( Context &tContext, char *pszBuffer, int iLength )
{
(void)tContext;
enum { BUF_SIZE=63 };
char szBuf[BUF_SIZE+1];
long lSeconds;
long lMicroSeconds;
PITimer_elapsed( tContext.tPIHTTP.pTimer, &lSeconds, &lMicroSeconds );
sprintf( szBuf, "%ld.%06ld", (long)lSeconds, (long)lMicroSeconds );
int iValueLen = strlen( szBuf );
int iLen = iValueLen < iLength ? iValueLen : iLength;
if ( iLen>0 )
{
assert( pszBuffer );
strncpy( pszBuffer, szBuf, iLen );
};
return iValueLen;
}
#undef S
#undef F
#undef C
#undef Q
#undef R
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
void Internal_InitShortcuts()
{
aFunctions['a'] = sc_a; /* administrator */
aFunctions['A'] = sc_A; /* IP address of remote client */
aFunctions['b'] = sc_b; /* bytes sent */
aFunctions['c'] = sc_c; /* content-type */
aFunctions['C'] = sc_C; /* content-type - incoming */
aFunctions['d'] = sc_d; /* debugging flag */
aFunctions['D'] = sc_D; /* handler time delta */
aFunctions['e'] = sc_e; /* SSL cipher name */
aFunctions['E'] = sc_E; /* error messages */
aFunctions['f'] = sc_f; /* filename */
aFunctions['g'] = sc_g; /* Using SSL?, g='Guarded'?, */
aFunctions['G'] = sc_G; /* SSL secret key size (g='Geheimnis') */
aFunctions['h'] = sc_h; /* remote host */
aFunctions['H'] = sc_H; /* request HTTP protocol */
aFunctions['i'] = sc_i; /* remote ident */
aFunctions['I'] = sc_I; /* path info section */
aFunctions['k'] = sc_k; /* thread id */
aFunctions['K'] = sc_K; /* SSL keysize */
aFunctions['l'] = sc_l; /* local address */
aFunctions['m'] = sc_m; /* request method from client */
aFunctions['M'] = sc_M; /* end of line sequence */
aFunctions['n'] = sc_n; /* name of current handler object */
aFunctions['N'] = sc_N; /* name of current handler phase */
aFunctions['o'] = sc_o; /* object name of virtual host */
aFunctions['p'] = sc_p; /* server port */
aFunctions['P'] = sc_P; /* process id */
aFunctions['q'] = sc_q; /* query string from client */
aFunctions['r'] = sc_r; /* request line */
aFunctions['R'] = sc_R; /* name of result code from last handler */
aFunctions['s'] = sc_s; /* status */
aFunctions['S'] = sc_S; /* server stamp */
aFunctions['t'] = sc_t; /* time in CLF */
aFunctions['T'] = sc_T; /* time taken to service request */
aFunctions['u'] = sc_u; /* remote user */
aFunctions['U'] = sc_U; /* URL requested */
aFunctions['v'] = sc_v; /* server name */
aFunctions['x'] = sc_x; /* authentication type */
aFunctions['X'] = sc_X; /* depth of request in subrequest hierarchy */
aFunctions['y'] = sc_y; /* content-length : outgoing */
aFunctions['Y'] = sc_Y; /* content-length : incoming */
aFunctions['z'] = sc_z; /* script name */
aFunctions['Z'] = sc_Z; /* path translated */
iShortcutsInitialized = 1;
}
/*____________________________________________________________________________*\
*
Class:
Description:
\*____________________________________________________________________________*/
class ShortcutComponent : public ComponentBase
{
private:
SCFnWrite fnWrite;
public:
ShortcutComponent( char c )
: fnWrite( 0 )
{
if ( !iShortcutsInitialized )
{
Internal_InitShortcuts();
};
fnWrite = aFunctions[c];
};
virtual void WriteDebugTree( int iIndent ) const
{
for(int i=0; i<iIndent; i++ )
{ cerr << INDENT_PATTERN; };
cerr << "Shortcut:" << endl;
};
virtual int Write( Context &tContext, char *pszBuffer, int iLength ) const
{
if ( !fnWrite )
{ return 0; };
return (fnWrite)( tContext, pszBuffer, iLength );
};
virtual int IsOK() const { return fnWrite!=0; };
virtual int IsStatic() const { return 0; /* some sc's only */ };
};
/*____________________________________________________________________________*\
*
Class:
Description:
Token class. Encapsulates a token in the input stream.
\*____________________________________________________________________________*/
class Token
{
public:
enum Type {
DOLLAR=1,
PERCENT,
OPEN_PAREN,
CLOSE_PAREN,
COMMA,
AMPERSAND,
NUMBER,
IDENTIFIER,
LITERAL,
OTHER
};
Type eType;
PIString sStr;
char cChar;
long lVal;
/* --- constructors --- */
Token( const Token &tT )
: eType( tT.eType ), sStr( tT.sStr ),
cChar( tT.cChar ), lVal( tT.lVal )
{};
Token( Type eTheType, char c ) : eType( eTheType ), cChar( c ), lVal( 0 )
{};
Token( char c ) : eType( OTHER ), cChar( c ), lVal( 0 )
{};
Token( Type eTheType, const PIString &sTheString )
: eType( eTheType ), sStr( sTheString ), cChar( '\0' ), lVal( 0 )
{
const char *pS = sStr;
cChar = pS ? *pS : '\0';
};
/* --- descriptions --- */
void GetDescription( PIString &sDescription )
{
switch( eType )
{
case DOLLAR:
case PERCENT:
case OPEN_PAREN:
case CLOSE_PAREN:
case COMMA:
case AMPERSAND:
case OTHER:
{
char szX[] = "X";
*szX = cChar;
sDescription = szX;
break;
};
case NUMBER: sDescription = "Number"; break;
case IDENTIFIER: sDescription = "Identifier"; break;
default:
assert( 0 ); sDescription = "Unknown";
};
};
};
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
class TokenSource
{
private:
PIString sExpression;
int iPos;
Token *pPushedBack;
public:
TokenSource( const char *pTheExpression )
: sExpression( pTheExpression ),
iPos( 0 ),
pPushedBack( 0 )
{
};
~TokenSource()
{
PI_DELETE( pPushedBack );
};
inline const PIString &GetRawString() { return sExpression; };
inline int GetPosition() { return iPos; };
private:
void Internal_PushBack()
{ assert( iPos>0 ); iPos--; };
Token *Internal_GetNextToken( PIString &sError )
{
enum {
NORMAL=1,
ESCAPED,
QUOTED,
COMMENT_START,
IN_COMMENT,
COMMENT_END,
IDENTIFIER
} eState = NORMAL;
/* --- persistent variables --- */
PIString sBuffer;
/* --- lexical state machine --- */
for(;;)
{
if ( sExpression.Len()==iPos )
{
switch( eState )
{
case NORMAL: return 0;
case COMMENT_START: return PI_NEW( Token( '/' ) );
case ESCAPED: return PI_NEW( Token( '\\' ) );
case IDENTIFIER:
return PI_NEW(Token( Token::IDENTIFIER, sBuffer ));
case QUOTED:
sError = "End of expression reading quoted literal.";
return 0;
case IN_COMMENT:
case COMMENT_END:
sError = "End of expression in reading comment.";
return 0;
default: assert( 0 ); return 0;
};
};
const char *pTmp = sExpression;
char c = pTmp[iPos++];
switch( eState )
{
case NORMAL:
if ( c=='\\' )
{ eState = ESCAPED; break; }
else if ( (isalpha(c)) || (c=='_') )
{
char szX[] = "X";
*szX = c;
sBuffer = szX;
eState = IDENTIFIER;
break;
};
switch( c )
{
case '\\': eState = ESCAPED; break;
case '\'': eState = QUOTED; break;
case '/': eState = COMMENT_START; break;
case '%': return PI_NEW( Token(Token::PERCENT, '%'));
case '$': return PI_NEW( Token(Token::DOLLAR, '$') );
case '(': return PI_NEW( Token(Token::OPEN_PAREN,'(') );
case ')': return PI_NEW( Token(Token::CLOSE_PAREN,')'));
case ',': return PI_NEW( Token(Token::COMMA,',') );
case '&': return PI_NEW( Token(Token::AMPERSAND,'&') );
default:;
return PI_NEW( Token( c ) );
};
break;
case COMMENT_START:
if ( c=='*' )
{ eState = IN_COMMENT; break; };
Internal_PushBack();
return PI_NEW( Token( '/' ) );
case IN_COMMENT:
if ( c=='*' )
{ eState = COMMENT_END; break; };
break;
case COMMENT_END:
if ( c=='/' )
{ eState = NORMAL; break; };
eState = IN_COMMENT;
break;
case IDENTIFIER:
if ( !(isalnum(c) || (c=='_')) )
{
eState = NORMAL;
Internal_PushBack();
return PI_NEW(Token( Token::IDENTIFIER, sBuffer ));
};
sBuffer.Concatenate( c );
break;
case ESCAPED:
eState = NORMAL;
switch( c )
{
case '\\': c = '\\'; break;
case 'a': c = '\a'; break;
case 'b': c = '\b'; break;
case 'f': c = '\f'; break;
case 'n': c = '\n'; break;
case 'r': c = '\r'; break;
case 't': c = '\t'; break;
case 'v': c = '\v'; break;
default:;
};
return PI_NEW( Token( c ) );
case QUOTED:
if ( c=='\'' )
{
eState = NORMAL;
return PI_NEW(Token( Token::LITERAL, sBuffer ));
};
sBuffer.Concatenate( c );
break;
default: assert( 0 ); return 0;
};
};
/* --- should never get here --- */
assert( 0 );
return 0;
};
public:
inline Token *GetNextToken( PIString &sError )
{
if ( pPushedBack )
{
Token *pTmp = pPushedBack;
pPushedBack = 0;
return pTmp;
};
return Internal_GetNextToken( sError );
};
inline void PushBack( Token *pToPushBack )
{
assert( !pPushedBack );
pPushedBack = pToPushBack;
};
};
/*____________________________________________________________________________*\
*
Function:
Synopsis:
Description:
\*____________________________________________________________________________*/
int Internal_ExpressionToString( Context &tContext,
_Pi3Expression *pExpr, char *pszBuffer, int iLength )
{
return pExpr->Write( tContext, pszBuffer, iLength );
}
/*____________________________________________________________________________*\
*
Class:
Description:
- make this more efficient by having functions be objects.
\*____________________________________________________________________________*/
class FunctionComponent : public ComponentBase
{
protected:
/* ---
encapsulation of a function arguments
--- */
class FunctionArgument
{
public:
enum { STRING=0, NUMBER, EXPRESSION } eType;
union {
PIString *pString;
int iNumber;
_Pi3Expression *pExpr;
};
FunctionArgument( PIString *pTheString )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -