windows-nt/Source/XPSP1/NT/net/ias/providers/nap/flex/xprparse.cpp
2020-09-26 16:20:57 +08:00

246 lines
5.7 KiB
C++

///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 1998, Microsoft Corp. All rights reserved.
//
// FILE
//
// xprparse.cpp
//
// SYNOPSIS
//
// This file implements the function IASParseExpression.
//
// MODIFICATION HISTORY
//
// 02/06/1998 Original version.
// 05/21/1999 Remove old style trace.
// 03/23/2000 Use two quotes to escape a quote.
//
///////////////////////////////////////////////////////////////////////////////
#include <ias.h>
#include <ExprBuilder.h>
#include <Parser.h>
#include <xprparse.h>
//////////
// Struct for converting an identifier to a logical token.
//////////
struct KeyWord
{
PCWSTR identifier;
IAS_LOGICAL_TOKEN token;
};
//////////
// Table of keywords. These must be sorted alphabetically.
//////////
const KeyWord KEYWORDS[] =
{
{ L"AND", IAS_LOGICAL_AND },
{ L"FALSE", IAS_LOGICAL_FALSE },
{ L"NOT", IAS_LOGICAL_NOT },
{ L"OR", IAS_LOGICAL_OR },
{ L"TRUE", IAS_LOGICAL_TRUE },
{ L"XOR", IAS_LOGICAL_XOR },
{ NULL, IAS_LOGICAL_NUM_TOKENS }
};
//////////
// Returns the IAS_LOGICAL_TOKEN equivalent for 'key' or IAS_LOGICAL_NUM_TOKENS
// if no such equivalent exists.
//////////
IAS_LOGICAL_TOKEN findKeyWord(PCWSTR key) throw ()
{
// We'll use a linear search since the table is so small.
for (const KeyWord* i = KEYWORDS; i->identifier; ++i)
{
int cmp = _wcsicmp(key, i->identifier);
// Did we find it ?
if (cmp == 0) { return i->token; }
// Did we we go past it ?
if (cmp < 0) { break; }
}
return IAS_LOGICAL_NUM_TOKENS;
}
//////////
// Special characters for parsing.
//////////
const WCHAR WHITESPACE[] = L" \t\n";
const WCHAR TOKEN_DELIMITERS[] = L" \t\n()";
//////////
// Parse a chunk of expression text and add it to the ExpressionBuilder.
//////////
void addExpressionString(ExpressionBuilder& expression, PCWSTR szExpression)
{
//////////
// Make a local copy because parser can temporarily modify the string.
//////////
size_t len = sizeof(WCHAR) * (wcslen(szExpression) + 1);
Parser p((PWSTR)memcpy(_alloca(len), szExpression, len));
//////////
// Loop through the expression until we hit the null-terminator.
//////////
while (*p.skip(WHITESPACE) != L'\0')
{
//////////
// Parentheses are handled separately since they don't have to be
// delimited by whitespace.
//////////
if (*p == L'(')
{
expression.addToken(IAS_LOGICAL_LEFT_PAREN);
++p;
}
else if (*p == L')')
{
expression.addToken(IAS_LOGICAL_RIGHT_PAREN);
++p;
}
else
{
// Get the next token.
const wchar_t* token = p.findToken(TOKEN_DELIMITERS);
// Check if it's a keyword.
IAS_LOGICAL_TOKEN keyWord = findKeyWord(token);
if (keyWord != IAS_LOGICAL_NUM_TOKENS)
{
// If it is a keyword, add it to the expression ...
expression.addToken(keyWord);
p.releaseToken();
}
else
{
// If it's not a keyword, it must be a condition object.
expression.addCondition(token);
p.releaseToken();
// Skip the leading parenthesis.
p.skip(WHITESPACE);
p.ignore(L'(');
// Skip the leading quote.
p.skip(WHITESPACE);
p.ignore(L'\"');
// We're now at the beginning of the condition text.
p.beginToken();
// Find the trailing quote, skipping any escaped characters.
while (p.findNext(L'\"')[1] == L'\"')
{
++p;
p.erase(1);
}
// Add the condition text.
expression.addConditionText(p.endToken());
p.releaseToken();
// Skip the trailing quote
p.ignore(L'\"');
// Skip the trailing parenthesis.
p.skip(WHITESPACE);
p.ignore(L')');
}
}
}
}
HRESULT
WINAPI
IASParseExpression(
PCWSTR szExpression,
VARIANT* pVal
)
{
if (szExpression == NULL || pVal == NULL) { return E_INVALIDARG; }
VariantInit(pVal);
try
{
ExpressionBuilder expression;
addExpressionString(expression, szExpression);
expression.detach(pVal);
}
catch (Parser::ParseError)
{
return E_INVALIDARG;
}
CATCH_AND_RETURN()
return S_OK;
}
IASNAPAPI
HRESULT
WINAPI
IASParseExpressionEx(
IN VARIANT* pvExpression,
OUT VARIANT* pVal
)
{
if (pvExpression == NULL || pVal == NULL) { return E_INVALIDARG; }
// If the VARIANT contains a single BSTR, we can just use the method
// defined above.
if (V_VT(pvExpression) == VT_BSTR)
{
return IASParseExpression(V_BSTR(pvExpression), pVal);
}
VariantInit(pVal);
try
{
ExpressionBuilder expression;
if (V_VT(pvExpression) == VT_EMPTY)
{
// If the variant is empty, the expression is always false.
expression.addToken(IAS_LOGICAL_FALSE);
}
else
{
CVariantVector<VARIANT> values(pvExpression);
for (size_t i = 0; i < values.size(); ++i)
{
// If we have more than one value, join them by AND's.
if (i != 0) { expression.addToken(IAS_LOGICAL_AND); }
if (V_VT(&values[i]) != VT_BSTR)
{
_com_issue_error(DISP_E_TYPEMISMATCH);
}
addExpressionString(expression, V_BSTR(&values[i]));
}
}
expression.detach(pVal);
}
catch (Parser::ParseError)
{
return E_INVALIDARG;
}
CATCH_AND_RETURN()
return S_OK;
}