Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

308 lines
9.2 KiB

/**********************************************************************/
/** Microsoft Windows/NT **/
/** Copyright(c) Microsoft Corp., 1991 **/
/**********************************************************************/
/*
rule.hxx
Storage, parsing and searching classes for NCPA/SPROLOG rule
handling.
OVERVIEW
This class lexically scans and parses text blocks in SProlog form.
The general form is:
<block> ::= <item> | <block> ;
<item> ::= <list> | '=' | variable | token ;
<list> ::= '(' <item>* ')' ;
<variable> ::= [A-Z][A-Za-z0-9_]* ;
<token> ::= number | atom | '|' ;
<number> ::= [0-9]+ ;
<atom> ::= [a-z][A-Za-z0-9_]* ;
Special parse flags control whether the outer class (CFG_RULE_SET)
allows variables or the eqivalence token ('=').
The cases are these:
1) SProlog facts only, such as when the Registry has
been browsed and a set of facts has been created.
No variables or list markers ('|') are allowed.
For example:
(dog spot)
(dog lassie)
(cat meu_meu)
2) SProlog rules and facts. Variables and list markers
are allowed. For example:
(dog spot)
(dog lassie)
(cat meu_meu)
(dog Anydog)
(topdog (Dog | RestOfDogList ) )
3) Results of a query. An SProlog query sequence might
appear as:
[query:] (dog X)
[answer:] X = spot
X = lassie
In this case, the '=' token is followed by exactly one
item; it may be a list.
Lists are constructed in the following manner. When a list is
found, a CFG_RULE_NODE is created and marked as a "list"; then
another node is created marked as a "nil", and linked as the
child of the list node. This "nil" node becomes the first
member of the list. As items are added to the list, the nil
node remains the physical first and last element of the list
since it's circular.
All of the tokens found at the uppermost lexical level of the
text block are stored as elements of a list representing the
entire block.
Note that this implies that a parse ALWAYS RESULTS IN AN
ADDITION BOUNDING LIST. This must be discarded (dereferenced)
by the caller if undesired.
CAVEATS
This class cannot handle all of the possible errors which may
occur in parsing. It is primarily a lexical scanner which aborts
on gross errors of syntax. It is up to the caller to determine
if the sequence of tokens is sensible. For example:
(dog (Dog | OtherDog | AnotherDog))
will be parsed and stored into its tree form without error.
However, such a sequence is completely impossible in SProlog.
(A list marker cannot be followed by another list marker at
the same lexical level.)
FILE HISTORY:
DavidHov 10/1/91 Created
DavidHov 3/19/92 Amended after code review
*/
#ifndef _RULE_HXX_
#define _RULE_HXX_
// Include definition of TEXT_BUFFER
#include "XtndStr.hxx"
enum CFG_RULE_NODE_TYPE
{
CRN_NIL, CRN_ROOT, CRN_RULE,
CRN_ATOM, CRN_STR, CRN_NUM,
CRN_LIST, CRN_VAR, CRN_EQUIV,
CRN_VBAR, CRN_MORE, CRN_ANY,
CRN_NUM_ANY, CRN_UNKNOWN
};
enum CFG_RULE_TYPE
{
CRT_TOP, CRT_CONTAINER, CRT_RULE, CRT_SUB
};
class CFG_RULE_NODE ; // Forward declarations
class CFG_RULE_SET ;
/*************************************************************************
NAME: CFG_RULE_NODE
SYNOPSIS: Rule element (node) class for NCPA configuration rules.
INTERFACE:
PARENT: none
USES: nothing
CAVEATS:
NOTES:
HISTORY:
DavidHov 10/1/91 Created
**************************************************************************/
CLASS_DECLSPEC CFG_RULE_NODE
{
public:
// Atom or string
CFG_RULE_NODE ( CFG_RULE_NODE * pcrnPrev,
HUATOM hUatom,
CFG_RULE_NODE_TYPE crnt = CRN_ATOM ) ;
// Number
CFG_RULE_NODE ( CFG_RULE_NODE * pcrnPrev, LONG lNumber ) ;
// Token or child list node
CFG_RULE_NODE ( CFG_RULE_NODE * pcrnPrev, CFG_RULE_NODE_TYPE crnt ) ;
~ CFG_RULE_NODE () ; // Delete tree
// Value query routines
CFG_RULE_NODE_TYPE QueryType () // Return type of node
{ return _ecnType ; }
HUATOM QueryAtom () // Return atom
{ return HUATOM( (UATOM *) _pv ) ; }
LONG QueryNumber () // Return number
{ return (LONG) _pv ; }
CFG_RULE_NODE * QueryList () // Return list NIL ptr
{ return (CFG_RULE_NODE *) _pv ; }
CFG_RULE_NODE * QueryNext () // Return ptr to next node
{ return _pcrnFwd->_ecnType == CRN_NIL ? NULL : _pcrnFwd ; }
CFG_RULE_NODE * QueryPrev () // Return ptr to previous node
{ return _pcrnBack->_ecnType == CRN_NIL ? NULL : _pcrnBack ; }
CFG_RULE_NODE * QueryParent () // Return ptr to parent node
{ return _pcrnParent ; }
CFG_RULE_NODE * QueryNth ( int cIndex ) ; // Return nth element of list
// UNICODE-compatible replacements for alphabetic/numeric operations
static BOOL cfIsDigit ( TCHAR ch ) ;
static BOOL cfIsAlpha ( TCHAR ch ) ;
static BOOL cfIsAlNum ( TCHAR ch ) ;
static TCHAR cfIsUpper ( TCHAR ch ) ;
static TCHAR cfIsLower ( TCHAR ch ) ;
static TCHAR cfToUpper ( TCHAR ch ) ;
static TCHAR cfToLower ( TCHAR ch ) ;
static LONG cfAtoL ( TCHAR * pszData ) ;
static INT cfScanAtomic ( const TCHAR * pszData,
const TCHAR * pszDelim,
TCHAR * pszBuffer,
INT cchBuffLen ) ;
protected:
CFG_RULE_NODE * _pcrnParent ; // Parent node
CFG_RULE_NODE * _pcrnFwd ; // Next node
CFG_RULE_NODE * _pcrnBack ; // Previous node
CFG_RULE_TYPE _ecrType ; // Rule type
CFG_RULE_NODE_TYPE _ecnType ; // Node type
void * _pv ; // Pointer to void
// Set the value and its type
void SetNumber ( LONG lNum )
{ _ecnType = CRN_NUM ; _pv = (void *) lNum ; }
void SetList ( CFG_RULE_NODE * pcrn,
CFG_RULE_NODE_TYPE crnt = CRN_RULE )
{ _ecnType = crnt ; _pv = (void *) pcrn ; }
void SetAtom ( HUATOM huaAtom,
CFG_RULE_NODE_TYPE crnt = CRN_ATOM )
{ _ecnType = crnt ; _pv = (void *) huaAtom ; }
void SetNil ()
{ _ecnType = CRN_NIL ; _pv = NULL ; }
CFG_RULE_NODE_TYPE SetType ( CFG_RULE_NODE_TYPE crnt )
{ return _ecnType = crnt ; }
CFG_RULE_NODE () ; // Create top of tree
void LinkAfter ( CFG_RULE_NODE * pcrnPrev ) ;
};
/*************************************************************************
NAME: CFG_RULE_SET
SYNOPSIS: Rule element tree class for NCPA configuration rules.
INTERFACE: Parse() Build the branches and leaves of the
tree by parsing the given block of text.
Textify() Convert the rule set to text.
PARENT: CFG_RULE_SET, BASE
USES: nothing
CAVEATS:
NOTES:
HISTORY:
DavidHov 10/1/91 Created
**************************************************************************/
const int PARSE_SUCCESSFUL = 1 ;
const int PARSE_INCOMPLETE = 0 ;
const int PARSE_ERR_UNBAL_PAREN = -1 ;
const int PARSE_ERR_BAD_TOKEN = -2 ;
const int PARSE_ERR_NO_MEMORY = -3 ;
const int PARSE_CLOSE_LEVEL = -4 ;
const int PARSE_CTL_FULL_SYNTAX = 1 ; // Full syntax allowed
const int PARSE_CTL_RSP_SYNTAX = 2 ; // Special query response syntax
CLASS_DECLSPEC CFG_RULE_SET :
public CFG_RULE_NODE,
public BASE
{
private:
const TCHAR * _pszData ;
const TCHAR * _pszNext ;
const TCHAR * _pszTok ;
USHORT _usParseCtl ;
int _iParseResult ;
ULONG _ulLength ;
int NextChar () ;
int PeekChar ()
{ return *_pszNext ; }
// Return the next token from the string.
// Store the token into "pszStr"; max length is "cbStr".
int NextToken ( TCHAR * pszStr, int cbStr ) ;
BOOL ParseLevel ( CFG_RULE_NODE * pcrn, int level ) ;
// Recursive helper routine for INF-to-SP conversion
INT ConvertInfList ( const TCHAR * * ppszIn,
TCHAR * * ppszOut, INT cLevel ) ;
INT TextifyInfList ( TEXT_BUFFER * ptxbBuff,
CFG_RULE_NODE * pcrnList,
INT cLevel,
INT cBaseLevel ) ;
public:
CFG_RULE_SET () ;
~ CFG_RULE_SET () ;
// Convert to/from text strings
APIERR Parse ( const TCHAR * pszText, USHORT usParseCtl ) ;
APIERR Textify ( TEXT_BUFFER * ptxbBuff ) ;
// Convert to/from INF-style lists
APIERR ParseInfList ( const TCHAR * pszText ) ;
APIERR TextifyInf ( TEXT_BUFFER * ptxBuff,
INT cLevel = 0 ) ;
int ParseResult ()
{ return _iParseResult ; }
const TCHAR * LastToken ()
{ return _pszTok ; }
};
#endif /* _RULE_HXX_ */