windows-nt/Source/XPSP1/NT/shell/evtmon/inc/emrule.h
2020-09-26 16:20:57 +08:00

1423 lines
53 KiB
C

/*****************************************************************************
emrule.h
Owner: DaleG
Copyright (c) 1992-1997 Microsoft Corporation
General Rule-Network Propagation Engine functions and prototypes
----------------------------------------------------------------------------
NOTE:
1. BAD CODE, but it works: FIsDelayFactor(),LpruldependFromCDelay() and
CDelayFromLpruldepend() rely upon the fact (?) that pointers
on the machines we support are never (?) small integers. But if
this should ever prove false, it would be bad. We should rewrite
this to either have a RULDEP structure (as does the rule compiler),
or make the list of dependencies indexes to rules, rather than
pointers.
*****************************************************************************/
#ifndef EMRULE_H
#include "msodbglg.h"
#include "emkwd.h"
#include "emrulini.h"
#include "emrultk.h"
MSOEXTERN_C_BEGIN // ***************** Begin extern "C" ********************
// REVIEW: configure this in makefile, so emtest (for example) can build
// debug without dynamic rules
#ifdef DEBUG
#ifndef YY_NODYNRULES
#define DYN_RULES 1
#endif
#endif
/*----------------------------------------------------------------------------
System limits
----------------------------------------------------------------------------*/
#define wDelayMax 100 // Maximum delay poss
#define irultkRuleMax 256 // Max events cached
#define iruldepAllocMax 256 // Max ruldeps alloced
#define ichRulNameMax 128 // Max trace name len
#define ichRulNameAllocMax 1024 // Max name alloc
/*************************************************************************
Types:
irul Rule node ID.
ruldep Rule node dependency link.
ruldepblk Rule node dependency link allocation structure.
sv Split Value structure.
rul Rule node structure.
ruls Rule state structure.
*************************************************************************/
/* I R U L */
/*----------------------------------------------------------------------------
%%Structure: IRUL
%%Contact: daleg
Rule Index definition
----------------------------------------------------------------------------*/
typedef short IRUL;
#define IrulFromTk(tk) ((IRUL) (tk))
#define TkFromIrul(irul) (irul)
// Lexer tokens: hard-coded rule node IDs
#define irulERROR tkERROR
#ifdef tkNil
#define irulNil tkNil
#else /* !tkNil */
#define irulNil 0
#endif /* tkNil */
// Is rule ID valid (not irulNil and not irulERROR)
#define FValidIrul(irul) \
((irul) > 0)
/* R U L D E P */
/*----------------------------------------------------------------------------
%%Structure: RULDEP
%%Contact: daleg
Rule node dependency structure.
This structure holds the dependency information that links a rule node
to its dependents.
----------------------------------------------------------------------------*/
typedef struct _RULDEP
{
struct _MSORUL *prul; // Node referenced
struct _RULDEP *pruldepNext; // Next dependency
// int cDelay; // Delay in eval
} RULDEP;
MSOAPI_(RULDEP *) _MsoPruldepNew( // Alloc blk of deps
int cruldep,
int fOnFreeList
);
// Return a new ruldep record from the free list (requires local var pruldep)
// Operates in either sequential mode (vlpruls->lpruldepNextFree) or free list
#define LpruldepNew() \
(vlpruls->lpruldepNextFree != NULL \
? (vlpruls->fSeqentialFreeRuldeps \
? vlpruls->lpruldepNextFree++ \
: (pruldep = vlpruls->lpruldepNextFree, \
vlpruls->lpruldepNextFree \
= pruldep->pruldepNext, \
pruldep->pruldepNext = NULL, \
pruldep)) \
: _MsoPruldepNew(iruldepAllocMax, TRUE))
// Push a ruldep record onto the free list
#define PushLpruldepOnFreeList(pruldep) \
((pruldep)->pruldepNext = vlpruls->lpruldepNextFree, \
vlpruls->lpruldepNextFree = (pruldep))
/* R U L D E P B L K */
/*----------------------------------------------------------------------------
%%Structure: RULDEPBLK
%%Contact: daleg
Rule node dependency allocation block structure.
This structure allows us to batch-allocate RULDEP records.
----------------------------------------------------------------------------*/
typedef struct _RULDEPBLK
{
struct _RULDEPBLK *lpruldepblkNext; // Next block
RULDEP rgruldep[1]; // Array of ruldeps
} RULDEPBLK;
/* R U L C X T */
/*----------------------------------------------------------------------------
%%Structure: RULCXT
%%Contact: daleg
(Rul)e (C)onte(x)t-group (T)able structure.
This structure allows the rule engine to support cheap sparse dependents
lists for special contexts.
The callback function allows us to perform any desired side effects
during the propagation, as well as offering the chance to optimize
the lookup algorithm.
----------------------------------------------------------------------------*/
typedef struct _RULCXT
{
struct _RULCXT *lprulcxtNext; // Next context
LPFNRULCXT lpfnrulcxt; // Callback fn
int iruldepMax; // Size of array
struct _RULCXL *rglprulcxl[1]; // Hash table
} RULCXT;
/* R U L C X L */
/*----------------------------------------------------------------------------
%%Structure: RULCXL
%%Contact: daleg
(Rul)e (C)onte(x)t-group (L)ist item structure.
This is the item used in the hash table of the RULCXT above.
----------------------------------------------------------------------------*/
typedef struct _RULCXL
{
IRUL irul; // Rule ID
struct _RULDEP *pruldep; // Dependent list
struct _RULCXL *lprulcxlNext; // Next in hash chain
} RULCXL;
#ifdef DEBUG
/* R U L N B L K */
/*----------------------------------------------------------------------------
%%Structure: RULNBLK
%%Contact: daleg
(Rul)e (N)ame block
Store dynamically constructed rule names.
----------------------------------------------------------------------------*/
typedef struct _RULNBLK
{
struct _RULNBLK *lprulnblkNext; // Next block
char rgch[1]; // Block of text
} RULNBLK;
char *LszGenNameForLprul( // Gen dyn rule name
struct _MSORUL *prul,
int irulAssert
);
char *SzSaveRulName(char *szName); // Save node name sz
char *LpchRulNameNew(int dichNeeded); // Get new name lpch
#endif /* DEBUG */
/* M S O R U L */
/*----------------------------------------------------------------------------
%%Structure: MSORUL
%%Contact: daleg
Rule node structure.
This structure holds the state information for a rule within the
propagation network.
ASSUMPTIONS:
1. The wDelayMask field only applies to rules, but it is (currently)
faster to not have to test for whether a node is a rule, by
merely leaving the field empty for values.
----------------------------------------------------------------------------*/
typedef long RULV;
typedef struct _MSORUL *MSOPRUL;
#pragma pack(2)
typedef struct _MSORUL
{
IRUL irul; // Rule ID
char rultType; // Type: rule/event
char ipfnrulscSeqCheck; // Fn to ensure contig
short rulevl; // Evaluation level
short birulDependsOn; // Depends on: nodes
SVL svl; // 32-bit storage area
#ifdef DEBUG
char const *lpchName; // Name or rule text
#endif /* DEBUG */
IRUL irulNextChanged; // Next changed value
union
{
short ipociiInstrs; // Interp instrs
short USEME_IN_EVENTS; // Unsed slot
};
short wIntervalCount; // Ensure contig seqs
short wDelayMask; // Delays as bit pos's
struct _MSORUL *prulNext; // Next node in queue
#ifdef DEBUG
IRUL irulNextTrace; // Next traced rule
short wDebugFlags; // Random debug flags
#endif /* DEBUG */
} MSORUL;
#pragma pack()
// Allocate new nodes
MSOAPI_(MSORUL *) MsoPrulNew(void); // Allocate new node
MSOAPI_(int) MsoFEnsureIrulAllocated(int irulMax); // Pre-allocated nodes
// Discard an existing rul node
#define DiscardIrul(irul) \
(vlpruls->irulLim--)
#define msoprulNil ((MSORUL *) -1) // NIL value for MSORUL
#define msoprulInactive ((MSORUL *) -2) // Node is deactivated
#define wRulTrue 1000
#define wRulFalse 0
// Rule node type flags: shared with emrulini.h and rulc.h
#define rultNil 0
#define rultRule 0x00 // Rule
#define rultEvent 0x01 // Event/Variable
#define rultPrimaryRule 0x02 // Rule auto-scheduled
#define rultImmediateRule 0x04 // Rule executes immed
#define rultPersistentRule 0x20 // Rule not cleared
#define rultAlwaysPersist 0x40 // Rule never cleared
#define rultSpecialKwd 0x80 // Node is generic type
// Debug check that rule is not marked as both NonTerminal and Seq
#define rultRuleMask 0x19
#ifdef NEVER
#define FRultRuleIs(rult, rultExpected) \
(((rult) & rultRuleMask) == ((rultExpected)))
#endif /* NEVER */
#ifdef DEBUG
#define rultDynActionRule 0x04 // Dyn DEBUG only
#define rultNonTermRule 0x08 // Dyn DEBUG only
#define rultSeqRule 0x10 // Dyn DEBUG only
#endif /* DEBUG */
/* R U L S */
/*----------------------------------------------------------------------------
%%Structure: RULS
%%Contact: daleg
Rule state structure.
This structure holds the state information for the rule engine.
----------------------------------------------------------------------------*/
typedef int (WIN_CALLBACK *LPFNRul)(IRUL irul); // Rule Eval function
typedef short (WIN_CALLBACK *PFNRULSC)(void); // Interval seq chk fn
typedef int (*PFNRULVT)(IRUL irul); // Rule V-Table
typedef struct _RULS
{
// Rule base limits
RULLIMS rullims; // Rule base limits
int irulMax; // Num nodes allocated
int irulLim; // Num nodes used
// Rule base state information
RULDEP ***rgrgpruldepDependents; // List of Dep lists
RULDEP **rgpruldepDependents; // Active Dep lists
MSORUL **lrglprulBlk; // Array of node arrays
int ilprulNodesLim; // #arrays of arrays
#ifdef DEBUG
MSORUL **rgprulNodes; // Debug node array
#endif /* DEBUG */
const short *prulgAppendTo; // Group linkages
const short *prulgAppendedFrom; // Group linkages
short const *rgrulevlRulevt; // Event_type eval lvls
int *rgrulevlRulevtLast; // Highest Q of rulevts
MSORUL **rgprulActiveQueues; // Active eval queues
MSORUL **rgprulDelayedQueues; // Delayed eval queues
MSORUL *lprulQPersistent; // Temp Q: persistent
int *rgirulRulevtChanged; // Nodes changed in evt
int *rgrulevtEval; // Pending rulevt eval
MSORULTKH *prultkhRulevtHistory; // Ev history for type
long *rgdtkiRulevt; // #times enter rulevt
const int *rgrulevtFromRulevl; // Trans lvls to evts
const short *lpgrpirulDependBack; // Back dependencies
LPFNRul lpfnEvalRule; // Evaluate rule code
PFNRULSC const *rgpfnrulscSeqCheck; // Interval seq chk fns
MSOKWTB **rgpkwtbKeyTables; // Keyword tables
// Allocation information
WORD fDynamicInit : 1; // Structs alloced?
WORD fDynAlloced : 1; // vlpruls alloced?
WORD fDependBackDynAlloced : 1; // Back deps alloced?
WORD fRgDependDynAlloced : 1; // Dep lists alloced?
WORD fDynRulesAlloced : 1; // Dyn rulebase alloc?
WORD fRgrulevlRulevtAlloced : 1; // Last lvl tbl alloc?
WORD fRgprulQueuesAlloced : 1; // Eval queues alloc?
WORD fRgrulevtFromRulevlAlloced : 1; // Lvl-evt tbl alloc?
WORD fRgprulNodesAlloced : 1; // DEBUG nd arr alloc?
int rulgCurr; // Current rule group
IRUL irulSelf; // irulSelf under eval
MSORUL *prulEvent; // Event causing eval
IRUL irulPrimaryEvent; // Primary ev of intvl
RULDEP *lpruldepNextFree; // Next free dep rec
RULDEPBLK *lpruldepblkDependBlocks; // List of dep blocks
RULCXT *lprulcxtActive; // Active context list
RULCXT **lrglprulcxtContexts; // List of cntx groups
int rulevtCurr; // Current event_type
int *prulevtEvalLim; // Num Ev types to eval
MSORUL *lprulQueue; // Current queue
int rulevlRultevtMin; // 1st eval lvl in evt
int rulevlRulevtLast; // Last eval lvl in evt
void *pociiDynRules; // Dyn-loaded rulebase
#ifdef DEBUG
char *lpchNames; // Name/string buf
char const * const *rgpchDynNames; // Interp: node names
int irulQTrace; // Backtrace list
int dichNameFree; // Num chars avail
char *lpchNameNextFree; // Next free name rgch
RULNBLK *lprulnblkNames; // Dyn name list
#endif /* DEBUG */
// Run-time flags
WORD fInited : 1; // Rule base inited?
WORD fNew : 1; // Rule base new?
WORD fSeqentialFreeRuldeps : 1; // Free ruldeps are seq
WORD fEvaluatingDeferred : 1; // Evaling deferred nd?
WORD fEvaluating: 1; // Eval recursion check
// Multiple Rule base support
struct _RULS *lprulsNext; // Next struct LIFO
// Allocation info
WORD fAllocedSpare1 : 1;
WORD fAllocedSpare2 : 1;
WORD fAllocedSpare3 : 1;
WORD fAllocedSpare4 : 1;
WORD fAllocedSpare5 : 1;
WORD fAllocedSpare6 : 1;
WORD fAllocedSpare7 : 1;
WORD fAllocedSpare8 : 1;
WORD fAllocedSpare9 : 1;
WORD fAllocedSpare10 : 1;
WORD fAllocedSpare11 : 1;
int ilprulNodesAllocFirstLim; // Start alloc'd nds +1
long lReturn; // Return value
LPV lpvSpare3;
LPV lpvSpare4;
LPV lpvSpare5;
LPV lpvSpare6;
LPV lpvSpare7;
LPV lpvSpare8;
LPV lpvSpare9;
LPV lpvSpare10;
LPV lpvSpare11;
// Debug logging
#ifdef DEBUG
unsigned int grfDebugLogFilter; // DEBUG: how to log
#endif /* DEBUG */
#ifdef DYN_RULES
// Dynamically-loaded rulebase support
struct _MSOOCIS *pocis; // Op-Code Interp State
short irulRuleInterpLim; // #Interpreted rules
short irulRuleInterpMac; // #Alloced inter ptrs
void **rgpociiRules; // Rule instructions
#endif /* DYN_RULES */
} RULS;
extern RULS *vlpruls; // Global rule state
//----------------------------------------------------
// If using debugger, an rulebase node's value is given by:
// rulv_<irul> == vlpruls->rgprulNodes[irul]->svl.lValue
//
// Or if the rulebase is statically initialized, and
// DEBUG_RULE_POINTERS is #defined then
// event FOO can be accessed as *prulFOO and
// rule 126 can be accessed as *prul126
//----------------------------------------------------
// Return the number of rules in rule base
#define IrulMax() (vlpruls->irulMax)
// Return the number of compiled rules in rule base
#define IrulCompiledMax() (vlpruls->rullims.irulRulesMax)
// Return the number of event_types in rule base
#define RulevtMax() RulevtMaxPruls(vlpruls)
// Return the number of event_types in rule base
#define RulevtMaxPruls(pruls) \
((pruls)->rullims.rulevtMax)
// Return the number of evaluation levels in rule base
#define RulevlMax() RulevlMaxPruls(vlpruls)
// Return the number of evaluation levels in rule base
#define RulevlMaxPruls(pruls) \
((pruls)->rullims.rulevlMax)
#define irulMaxAlloc 128 // Max nodes/array
#define cbfIrulShift 7 // #bits irulMaxAlloc
#define wIrulMask 0x7F // Mask: irulMaxAlloc
#define ilprulMaxAlloc 256L // Max arrays of arrys
///#define irulMaxAlloc 2048 // Max nodes/array
///#define cbfIrulShift 11 // #bits irulMaxAlloc
///#define wIrulMask 0x7FF // Mask: irulMaxAlloc
///#define ilprulMaxAlloc 100L // Max arrays of arrys
///#define irulMaxAlloc 1024 // Max nodes/array
///#define cbfIrulShift 10 // #bits irulMaxAlloc
///#define wIrulMask 0x3FF // Mask: irulMaxAlloc
///#define ilprulMaxAlloc 100L // Max arrays of arrys
// Return the rule node structure pointer for the rule ID
#define LprulFromIrul(irul) \
(&vlpruls->lrglprulBlk \
[(irul) >> cbfIrulShift] [(irul) & wIrulMask])
// Return the rule ID of the rule node structure pointer
#define IrulFromLprul(prul) \
((prul)->irul)
// Return the Lim irul value for iruls that are contiguous with the irul
#define IrulLimContig(irul) \
((((irul) >> cbfIrulShift) << cbfIrulShift) + irulMaxAlloc)
// Return whether rule node is a primary rule
#define FPrimaryRule(prul) ((prul)->rultType & rultPrimaryRule)
#ifdef NEVER
// Return whether rule node is a action rule
#define FActionRule(prul) ((prul)->wDebugFlags & rultActionRule)
#endif /* NEVER */
#ifdef DEBUG
// Return whether rule node is a non-terminal rule (then)
#define FNonTermRule(prul) ((prul)->wDebugFlags & rultNonTermRule)
// Return whether rule node is a sequence rule (...)
#define FSeqRule(prul) ((prul)->wDebugFlags & rultSeqRule)
#endif /* DEBUG */
// Return whether the node ID refers to an event node
#define FIsEventIrul(irul) FIsEventPrul(LprulFromIrul(irul))
// Return whether the node is an event node
#define FIsEventPrul(prul) ((prul)->rultType & rultEvent)
// Return whether the node is a rule node
#define FIsRulePrul(prul) (!FIsEventPrul(prul))
#define IMMEDIATE_RULES
#ifdef IMMEDIATE_RULES
// Return whether rule node is a sequence rule (...)
#define FImmediateRulePrul(prul) ((prul)->rultType & rultImmediateRule)
#endif /* IMMEDIATE_RULES */
// Return whether the node is an *undefined* event
#define FSpecialKwdIrul(irul) \
FSpecialKwdLprul(LprulFromIrul(irul))
// Return whether the node is an *undefined* event
#define SetFSpecialKwdIrul(irul) \
SetFSpecialKwdLprul(LprulFromIrul(irul))
// Return whether the node is an *undefined* event
#define FSpecialKwdLprul(prul) ((prul)->rultType & rultSpecialKwd)
// Return whether the node is an *undefined* event
#define SetFSpecialKwdLprul(prul) \
((prul)->rultType |= rultSpecialKwd)
// Return whether rule node can persist in delayed queue in soft resets
#define FPersistentLprul(prul) \
((prul)->rultType & rultPersistentRule)
// Mark that rule node can persist in delayed queue in soft resets
#define SetFPersistentIrul(irul) \
SetFPersistentLprul(LprulFromIrul(irul))
// Mark that rule node can persist in delayed queue in soft resets
#define SetFPersistentLprul(prul) \
((prul)->rultType |= rultPersistentRule)
// Return whether rule node can persist in delayed queue in all resets
#define FAlwaysPersistLprul(prul) \
((prul)->rultType & rultAlwaysPersist)
// Mark that rule node can persist in delayed queue in all resets
#define SetFAlwaysPersistIrul(irul) \
SetFAlwaysPersistLprul(LprulFromIrul(irul))
// Mark that rule node can persist in delayed queue in all resets
#define SetFAlwaysPersistLprul(prul) \
((prul)->rultType |= rultAlwaysPersist)
// Return whether rule node can persist in delayed queue
#define FPersistLprulGrf(prul, grf) \
((prul)->rultType & (grf))
// Return the value for the current rule
#define RulvSelf() \
RulvOfIrul(irulSelf)
// Set the value for the current rule
#define SetRulvSelf(rulv) \
SetRulvOfIrul(irulSelf, (rulv))
// Increment the value for the current rule
#define IncrRulvSelf(drulv) \
IncrRulvOfIrul(irulSelf, (drulv))
// Return the value1 for the current rule
#define Rulv1Self() \
Rulv1OfIrul(irulSelf)
// Set the value1 for the current rule
#define SetRulv1Self(rulv) \
SetRulv1OfIrul(irulSelf, (rulv))
// Increment the value1 for the current rule
#define IncrRulv1Self(drulv) \
IncrRulv1OfIrul(irulSelf, (drulv))
// Return the value2 for the current rule
#define Rulv2Self() \
Rulv2OfIrul(irulSelf)
// Set the value2 for the current rule
#define SetRulv2Self(rulv) \
SetRulv2OfIrul(irulSelf, (rulv))
// Increment the value2 for the current rule
#define IncrRulv2Self(drulv) \
IncrRulv2OfIrul(irulSelf, (drulv))
// Return the value for the rule ID
#define RulvOfIrul(irul) \
(LprulFromIrul(irul)->svl.lValue)
// Set the value for the rule ID
#define SetRulvOfIrul(irul, rulv) \
(LprulFromIrul(irul)->svl.lValue = (rulv))
// Increment the value1 field for the rule ID
#define IncrRulvOfIrul(irul, drulv) \
IncrRulvOfLprul(LprulFromIrul(irul), (drulv))
// Return the lValue field for a rule node
#define RulvOfLprul(prul) ((prul)->svl.lValue)
// Set the lValue field for a rule node
#define SetRulvOfLprul(prul, w) ((prul)->svl.lValue = (w))
// Increment the value1 field for a rule node
#define IncrRulvOfLprul(prul, drulv) ((prul)->svl.lValue += (drulv))
// Set the value for the rule ID
#define PlValueOfIrul(irul) \
(&LprulFromIrul(irul)->svl.lValue)
// Return the value1 field for the rule ID
#define Rulv1OfIrul(irul) \
Rulv1OfLprul(LprulFromIrul(irul))
// Set the value1 field for the rule ID
#define SetRulv1OfIrul(irul, rulv) \
SetRulv1OfLprul(LprulFromIrul(irul), (rulv))
// Increment the value1 field for the rule ID
#define IncrRulv1OfIrul(irul, drulv) \
IncrRulv1OfLprul(LprulFromIrul(irul), (drulv))
// Return the value2 field for the rule ID
#define Rulv2OfIrul(irul) \
Rulv2OfLprul(LprulFromIrul(irul))
// Set the value2 field for the rule ID
#define SetRulv2OfIrul(irul, rulv) \
SetRulv2OfLprul(LprulFromIrul(irul), (rulv))
// Increment the value2 field for the rule ID
#define IncrRulv2OfIrul(irul, drulv) \
IncrRulv2OfLprul(LprulFromIrul(irul), (drulv))
// Return the value1 field for a rule node
#define Rulv1OfLprul(prul) W1OfPsv(PsvOfLprul(prul))
// Set the value1 field for a rule node
#define SetRulv1OfLprul(prul, w) SetW1OfPsv(PsvOfLprul(prul), (w))
// Increment the value1 field for a rule node
#define IncrRulv1OfLprul(prul, dw) IncrW1OfPsv(PsvOfLprul(prul), (dw))
// Return the value2 field for a rule node
#define Rulv2OfLprul(prul) W2OfPsv(PsvOfLprul(prul))
// Set the value2 field for a rule node
#define SetRulv2OfLprul(prul, w) SetW2OfPsv(PsvOfLprul(prul), (w))
// Increment the value2 field for a rule node
#define IncrRulv2OfLprul(prul, dw) IncrW2OfPsv(PsvOfLprul(prul), (dw))
// Return the Split Value pointer of a node
#define PsvOfLprul(prul) (&(prul)->svl.sv)
// Return the value1 field for an rule node
#define Rulv1(rulv) W1OfPsv((SV *) &(rulv))
// Set the value1 field for a node
#define SetRulv1(rulv, w) SetW1OfPsv(((SV *) &(rulv)), (w))
// Return the value2 field
#define Rulv2(rulv) W2OfPsv((SV *) &(rulv))
// Set the value2 field for a node
#define SetRulv2(rulv, w) SetW2OfPsv(((SV *) &(rulv)), (w))
// Return the confidence value of a node node
#define WConfidence(prul) Rulv1OfLprul(prul)
// Set the confidence value of a node node
#define SetConfidence(prul, wValue) SetRulv1OfLprul((prul), (wValue))
// Return the doubt value of a node node
#define WDoubt(prul) Rulv2OfLprul(prul)
// Set the doubt value of a node node
#define SetDoubt(prul, wValue) SetRulv2OfLprul((prul), (wValue))
// OBSOLETE FORMS OF MACROS
#define WValueOfIrul(irul) RulvOfIrul(irul)
#define SetWValueOfIrul(irul, rulv) SetRulvOfIrul(irul, rulv)
#define WRulValue1(prul) Rulv1OfLprul(prul)
#define SetWRulValue1(prul, w) SetRulv1OfLprul((prul), (w))
#define WRulValue2(prul) Rulv2OfLprul(prul)
#define SetWRulValue2(prul, w) SetRulv2OfLprul((prul), (w))
// Return the rule node for the rule value
#define LprulOfWValue(lplValue) \
((MSORUL *) \
(((char *) lplValue) - CchStructOffset(MSORUL, svl.lValue)))
#ifdef DEBUG
// Return the value name or rule text of the rule node structure pointer
#define LpchRulName(prul) ((prul)->lpchName)
// Return the value name or rule text of the rule node structure pointer
#define LpchIrulName(irul) LpchRulName(LprulFromIrul(irul))
// Return debug rule name for dynamic rule
#define PszNameDynLprul(prul) \
(vlpruls->rgpchDynNames[(prul)->irul - IrulCompiledMax()])
#endif /* DEBUG */
// Return the node evaluation level for the node
#define RulevlOfPrul(prul) \
(prul->rulevl)
// Return the event_type for the node
#define RulevtOfLprul(prul) \
RulevtOfRulevl(RulevlOfPrul(prul))
// Return the event_type for the evaluation level
#define RulevtOfRulevl(rulevl) \
(vlpruls->rgrulevtFromRulevl[rulevl])
// Return the rule queue of the rule level
#define LplprulQueueOf(rulevl) (&vlpruls->rgprulActiveQueues[rulevl])
// Return the delayed-evaluation rule queue of the event_type
#define LplprulDelayedQueueOf(rulevt) \
(&vlpruls->rgprulDelayedQueues[rulevt])
// Return the minimum evaluation level of the event_type
#define RulevlMinOfRulevt(rulevt) \
(vlpruls->rgrulevlRulevt[(rulevt)])
// Return the maximum evaluation level of the event_type
#define RulevlMaxOfRulevt(rulevt) \
(vlpruls->rgrulevlRulevt[(rulevt) + 1])
// Return the list of dependent node references of node ID
#define LpruldepFromIrul(irul) \
(vlpruls->rgpruldepDependents[irul])
// Return the list of dependent node references of node
#define LpruldepGetDependents(prul) \
LpruldepFromIrul(IrulFromLprul(prul))
// Set the list of dependent node references of node ID
#define SetLpruldepFromIrul(irul, pruldep) \
(vlpruls->rgpruldepDependents[irul] = (pruldep))
// Set the list of dependent node references of node
#define LpruldepSetDependents(prul, pruldep) \
SetLpruldepFromIrul(IrulFromLprul(prul), (pruldep))
// Return the list of dependent node references of node ID for specific group
#define LpruldepFromRulgIrul(rulg, irul) \
(*LplpruldepForRulgIrul(rulg, irul))
// Set the list of dependent node references of node ID for specific group
#define SetLpruldepFromRulgIrul(rulg, irul, pruldep) \
(*LplpruldepForRulgIrul(rulg, irul) = (pruldep))
// Return the address of the start of a ruldep list for the irul and group
#define LplpruldepForRulgIrul(rulg, irul) \
(&(vlpruls->rgrgpruldepDependents[rulg][irul]))
// Return whether a dependent reference is in fact a delay specfication
#define FIsDelayFactor(lprulDepend) \
((unsigned long) (lprulDepend) < wDelayMax)
// Return the delay value associated with the dependency record
#define CDelayFromLpruldepend(lprulDepend) \
((int) ((unsigned long) lprulDepend))
// Return a dependency record to represent the delay factor
#define LpruldependFromCDelay(cDelay) \
((MSORUL *) (cDelay))
// Add a delay to the delay field of a delayed rule
#define AddCDelayToLprul(prul, cDelay) \
((prul)->wDelayMask |= (cDelay))
// Return whether a rule has any delay factor
#define FHaveCDelay(prul) \
((prul)->wDelayMask)
// Return whether a rule has a specific delay factor
#define FHaveCDelayOf(prul, cDelay) \
((prul)->wDelayMask & (cDelay))
// Decrement the node's delay counts (by shifting right)
#define DecrementCDelaysOfLprul(prul) \
((prul)->wDelayMask >>= 1)
// Return whether the (event) node is marked for history recording
#define FHistoryRecordLprul(prul) \
(TRUE) // First version
// ((prul)->fRecordHistory) // Correct version
// Return whether node must check interval counts to detect seq discontinuities
#define FIntervalsSeqCheckedPrul(prul) \
((prul)->ipfnrulscSeqCheck)
// Return interval counts associated with node that has sequence checking
#define WIntervalsSeqCheckedPrul(prul) \
((*vlpruls->rgpfnrulscSeqCheck[(prul)->ipfnrulscSeqCheck])())
// Return whether the rule base is initialized
#define FRulesInited(lpruls) (lpruls != NULL && lpruls->fInited)
// Return the op-code instructions for an interpreted rule ID
#define PociiForIrul(irul) \
PociiForPrul(LprulFromIrul(irul))
// Return the op-code instructions for an interpreted rule
#define PociiForPrul(prul) \
((MSOOCII *) vlpruls->rgpociiRules[((prul)->ipociiInstrs)])
// Return any group(s) that append(s) the current group
#define RulgAppendedFrom(rulg) \
(vlpruls->prulgAppendedFrom[rulg])
// Return the list of groups that append from other groups
#define PrulgAppendedFrom() \
(vlpruls->prulgAppendedFrom)
// Return the group (if any) that the current group appends to
#define RulgAppendTo(rulg) \
(vlpruls->prulgAppendTo[rulg])
// Return the list of groups that append to other groups
#define PrulgAppendTo() \
(vlpruls->prulgAppendTo)
#define rulgNil (-1) // "No" rule group
#define rulevtNil (-1) // "No" event type
#ifdef DEBUG
// Return whether node is marked for automatic backtracing */
#define FTraceLprul(prul) \
((prul)->irulNextTrace != 0)
#endif /* DEBUG */
// Return the list of nodes that current node depends upon
#define LpirulGetDependsOn(prul) \
(&vlpruls->lpgrpirulDependBack[(prul)->birulDependsOn])
/*************************************************************************
Prototypes and macros for rule.c
*************************************************************************/
#ifndef max
#define max(a,b) ((a) > (b) ? (a) : (b))
#endif /* !max */
#ifndef min
#define min(a,b) ((a) < (b) ? (a) : (b))
#endif /* !max */
// Push the node onto the queue
#define PushLprul(prul, lplprulQ) \
((prul)->prulNext = *(lplprulQ), \
*(lplprulQ) = (prul))
// Pop the node from the queue into the variable
#define PopLprul(lplprul, lplprulQ) \
(*lplprul = *lplprulQ, \
*lplprulQ = (*lplprul)->prulNext, \
(*lplprul)->prulNext = 0)
// Push event node into Auto-Clear (Changed) list
#define PushLpRulChanged(prul) \
if ((prul)->irulNextChanged == 0) \
{ \
int rulevt = RulevtOfLprul(prul); \
\
(prul)->irulNextChanged \
= vlpruls->rgirulRulevtChanged[rulevt]; \
vlpruls->rgirulRulevtChanged[rulevt] = IrulFromLprul(prul); \
}
// Mark event as never Auto-Clearing
#define SetNoAutoClearRulv(rulv) \
(LprulFromRulv(rulv)->irulNextChanged = irulNoAutoClear)
#define SetNoAutoClearLprul(prul) \
((prul)->irulNextChanged = irulNoAutoClear)
#define irulChangedNil -1
#define irulNoAutoClear -2
// Return the offset of a field from the start of its typedef'd structure
// NOTE: THIS IS TRICKY CODE, BUT COMPLETELY LEGAL C!!
// To understand it, remember that 0 is a valid pointer for ALL types!
#define CchStructOffset(type, field) \
(((char *) (&((type *) 0)->field)) - ((char *) 0))
// Call Rule Evaluation function provided by Application
#define FEvalRule(irul) \
(*vlpruls->lpfnEvalRule)(irul)
#ifndef STATIC_LINK_EM
MSOAPI_(RULS **) MsoPvlprulsMirror(RULS **pvlprulsApp); // Exchange &vlpruls
#else /* STATIC_LINK_EM */
#define MsoPvlprulsMirror(pvlprulsApp) pvlprulsApp
#endif /* !STATIC_LINK_EM */
MSOAPI_(int) MsoFInitRules( // Init rule base
LPFNRulinit lpfnRulInit,
RULS *lpruls
);
IRUL IrulDefineEvent(int rulevt, char *szName); // Define simple event
MSOAPI_(MSOKWD *) MsoFDefineStringKwdEvent( // Define str kwd event
int rulevt,
char *szName,
XCHAR *pxch,
int cch,
int ikwtb
);
MSOAPI_(MSOKWDLH *) MsoFDefineIntegerKwdEvent( // Define int kwd event
int rulevt,
char *szName,
long lValue,
int ikwtb
);
MSOAPI_(void) MsoClearRules(void); // Clear nodes & state
MSOAPI_(void) MsoClearEventsForRulevts( // Clr rg of ev types
int rulevtFirst,
int drulevtCount,
int fSavePersistentDelayed,
int fClearChanged,
int fClearIntervalCounts
);
MSOAPI_(void) MsoRestorePersistentDelayedRules(void); // Restore delayed Q
MSOAPI_(int) MsoFAddPruldepDependent( // Add dependent link
IRUL irul,
MSORUL *prulDependent,
int cDelay,
int rulg
);
MSOAPI_(void) MsoFixUpPruldeps( // Fix up after insert
IRUL irul,
int rulg,
int rulgBase,
RULDEP *lpruldepOldList,
RULDEP *lpruldepNewList
);
MSOAPI_(int) MsoFDelPruldepDependent( // Del dependent link
IRUL irul,
MSORUL *prulDependent,
int rulg,
int fDiscard
);
MSOAPI_(void) MsoSetActiveRuls(RULS *pruls); // Set curr vlpruls
MSOAPI_(void) MsoFreeRuleMem(RULS *pruls); // Free rule memory
#ifdef OFFICE_BUILD
MSOAPI_(void) MsoMarkRuleMem(RULS *pruls); // Mark rule mem used
#endif /* OFFICE_BUILD */
MSOAPI_(void) MsoSetEventTypeRulevt(int rulevt); // Change event_types
MSOAPI_(void) MsoClearChangedEventsForRulevt(int rulevt);// Clr event_type vals
void RemoveLprulChanged(MSORUL *prul); // Un-auto-clear event
MSOAPI_(int) MsoEvaluateEvents(int rulevt); // Event evaluation
MSOAPI_(int) MsoFEvalIrul(IRUL irul); // Eval single node
MSOAPI_(void) MsoDelaySignalIrul( // Signal node w/delay
IRUL irul,
long lValue,
int cDelay
);
MSOAPI_(void) MsoDelaySignalIrulFrom( // Signal node w/delay
IRUL irul,
IRUL irulFrom,
int cDelay
);
MSOAPI_(void) MsoSignalIrul(IRUL irul, long lValue); // Cond schedule irul
#define PushIrulToEval(irul, lValue) \
MsoSignalIrul(irul, lValue)
MSOAPI_(void) MsoScheduleIrul(IRUL irul, long lValue); // Schedule rule to run
#ifdef DEBUG
MSOAPI_(void) MsoScheduleIrulDebug(IRUL irul, long lValue);// Log and schedule
MSOAPI_(void) MsoScheduleIrulDebugMso(IRUL irul, long lValue);//Log &sched MSO
#else
#define MsoScheduleIrulDebug MsoScheduleIrul
#define MsoScheduleIrulDebugMso MsoScheduleIrul
#endif /* DEBUG */
MSOAPI_(void) MsoDelayScheduleIrul( // Schedule after delay
IRUL irul,
long lValue,
int cDelay
);
#ifdef DEBUG
MSOAPI_(void) MsoDelayScheduleIrulDebug( // Log and schedule
IRUL irul,
long lValue,
int cDelay
);
#else
#define MsoDelayScheduleIrulDebug MsoDelayScheduleIrul
#endif /* DEBUG */
MSOAPI_(void) MsoDelayScheduleIrulFrom( // Sched, pass value
IRUL irul,
IRUL irulFrom,
int cDelay
);
MSOAPI_(int) MsoFEvalIrulImmediately( // Eval irul now
IRUL irul,
long lValue
);
MSOAPI_(void) MsoPushLprulDependents(MSORUL *prul); // Push dependents
MSOAPI_(void) MsoPushDelayedEvalForRulevt(int rulevt); // Push delayed nodes
MSOAPI_(void) MsoAutoClearIrul(IRUL irul); // Mark node for clear
MSOAPI_(int) MsoFAliasPrulPrul( // Ret if 2 are aliases
MSORUL *prul,
MSORUL *prulTarget
);
void RecordLprulHistory(MSORUL *prul); // Push ev into hist
#ifdef NEVER
MSOAPI_(int) MsoFIrulHistoryValueWas( // Look 4 event in hist
int dirultkBackwards,
long *lpwVar
);
#endif // NEVER
#ifdef NEED_AS_FUNCTION
void SetCurrRulg(int rulgGroup); // Set rule group
#endif /* NEED_AS_FUNCTION */
MSOAPI_(void) MsoSignalEventIrul(IRUL irul, long lValue);// Signal an event
MSOAPI_(void) MsoSignalEventIrulFrom( // Signal ev from node
IRUL irul,
IRUL irulFrom
);
#ifdef NEVER
MSOAPI_(void) MsoSetRuleConfid(IRUL irul, int wFactor); // Set confidence val
#endif // NEVER
// Schedule a node for deferred evaluation, based upon a decision rule
// This macro gets invoked twice. See _MsoFDeferIrul() for details.
#define FDeferIrul(irul) \
(vlpruls->fEvaluatingDeferred || _MsoFDeferIrul(irul))
#define FDeferIrulExpr(irul, lExpr) \
(vlpruls->fEvaluatingDeferred \
|| (((int) lExpr) && _MsoFDeferIrul(irul)))
#define FDeferIrulExprL(irul, lExpr, lValue) \
(vlpruls->fEvaluatingDeferred \
|| (((int) lExpr) && _MsoFDeferIrulL((irul), (lValue))))
#define IrulPickDeferred(irulDecision) \
MsoIrulPickDeferred(irulDecision)
MSOAPI_(int) _MsoFDeferIrul(IRUL irul); // Add to defer list
MSOAPI_(int) _MsoFDeferIrulL(IRUL irul, long lValue); // Add to defer w/value
MSOAPI_(IRUL) MsoIrulPickDeferred(IRUL irulDecision); // Pick from defer list
MSOAPI_(void) MsoSetRulNotify( // Set up notification
long lExprValue, // Really an int
IRUL irulDecision,
IRUL irulNotify
);
MSOAPI_(int) MsoFRulNotify(long wNotify); // Notify on next eval
MSOAPI_(int) MsoFRulNotifyImmediately(long wNotify); // Notify immediately
MSOAPI_(long) MsoRulvElement(IRUL irulArray, IRUL iirul);// Get value of array
MSOAPI_(void) MsoSetElementRulv( // Set value of array
IRUL irulArray,
IRUL iirul,
long lValue
);
MSOAPI_(void) MsoSetAllElementsToRulv( // Set all vals of arr
IRUL irulArray,
IRUL cirul,
long lValue
);
/* M S O F A C T I V A T E I R U L */
/*----------------------------------------------------------------------------
%%Function: MsoFActivateIrul
%%Contact: daleg
Activate a node in the rulebase
----------------------------------------------------------------------------*/
_inline int MsoFActivateIrul(IRUL irul) // Activate a node
{
MSOPRUL prul = LprulFromIrul(irul);
if (prul->prulNext == msoprulInactive)
{
prul->prulNext = (MSOPRUL) NULL;
return TRUE;
}
else
return FALSE;
}
/* M S O F D E A C T I V A T E I R U L */
/*----------------------------------------------------------------------------
%%Function: MsoFDeactivateIrul
%%Contact: daleg
Deactivate a node in the rulebase
----------------------------------------------------------------------------*/
MSOAPI_(int) _MsoFDeactivateIrul(IRUL irul); // Deactivate a node
_inline int MsoFDeactivateIrul(IRUL irul)
{
MSOPRUL prul = LprulFromIrul(irul);
if (prul->prulNext == NULL)
{
prul->prulNext = msoprulInactive;
return TRUE;
}
else
return _MsoFDeactivateIrul(irul);
}
MSOAPI_(int) MsoFDeleteIrul(IRUL irul, int rulg); // Delete a node
/*************************************************************************
Prototypes and macros for rultest.c and rulconcl.c.
These prototypes "Hungarianize" the rule code so that the rule
authors do not have to know Hungarian, but it is preserved within
the application code.
*************************************************************************/
// Return the current interval number for the event_type
#define CIntervalsRulevt(rulevt) \
(vlpruls->rgdtkiRulevt[rulevt])
// OBSOLETE: Return the current interval number for the event_type
#define CIntervalsRsct(rulevt) CIntervalsRulevt(rulevt)
// Increment the current interval number for the event_type
#define IncrIntervalsRsct(rulevt, dc) \
(vlpruls->rgdtkiRulevt[rulevt] += (dc))
#ifdef NEVER
// Set long value of a node and force propagation
#define SetValue(wVar, lValue) \
SignalEvent(wVar, lValue)
#endif /* NEVER */
// Convert a "variable" event reference to an node address
#define LprulFromRulv(rulvVar) \
LprulOfWValue(&(rulvVar))
// Notify a node, on its next evaluation pass
#define FNotify(rgwVar) \
MsoFRulNotify(rgwVar)
// Notify an action rule, immediately
#define FNotifyImmediately(rgwVar) \
MsoFRulNotifyImmediately(rgwVar)
// Indicate the next event_type to enter when current event_type is exited
#define SetNextEventType(rulevt) \
if (vlpruls->prulevtEvalLim \
< vlpruls->rgrulevtEval + RulevtMax()) \
(*vlpruls->prulevtEvalLim++ = (rulevt)); \
else \
AssertSz0(FALSE, "Exceeded max number of rulevts to eval");
// Force delayed evaluation of rule of given ID: GENERATED BY RULE COMPILER
#define DelayEvalIrul(irul, cDelay) \
MsoDelayScheduleIrulFrom((irul), (irul), (cDelay))
// Return whether the dirultkBackwards'th previous value was the given event
#define ValueWas(dirultkBackwards, wVar) \
MsoFIrulHistoryValueWas(dirultkBackwards, &(wVar))
// Find the given value in its event_type history, and return the (neg) offset
#define FindPrevValueFrom(dirultkBackwards, wVar) \
DirultkFindPrevValueFrom(dirultkBackwards, &(wVar))
// Mark event/rule for automatic clearing on event_type exit
#define AutoClear(irul) \
MsoAutoClearIrul(irul)
// Mark expression as exempt from dependency linkage in rule if
#define Value(expr) (expr)
// Push all dependents of node of ID onto their evaluation queues
#define Propagate(irul) \
MsoPushLprulDependents(LprulFromIrul((int) irul))
// Evaluate the rule at normal time
#define GoToRule(irul) \
MsoDelayScheduleIrul((irul), TRUE, 0 /* cDelay */)
// Evaluate the rule at normal time
#define GoToIrul(irul) \
MsoDelayScheduleIrulFrom((IRUL) (irul), (irulSelf), 0 /* cDelay */)
// Evaluate the rule after delay of 1, incrementing value
#define GoToIrulNoValue(irul) \
MsoDelayScheduleIrulFrom \
((IRUL) (irul), (IRUL) (irul), 1 /* cDelay */)
// Evaluate the rule at normal time
#define GoToDirul(dirul) \
MsoDelayScheduleIrulFrom \
((IRUL) (irulSelf) + (dirul), (irulSelf), 0 /* cDelay */)
// Evaluate the rule after delay of 1
#define DelayGoToRule(irul) \
DelayGoToIrulNoValue(irul)
// Signal the event with the given value
#define SignalIrul(irul, lValue) \
MsoSignalIrul(irul, lValue)
// Signal the event with the given value
#define SignalEvent(wVar, lValue) \
MsoSignalEventIrul(IrulFromLprul(LprulFromRulv(wVar)), (lValue))
// Signal the event with the given value
#define SignalEventIrul(irul, lValue) \
MsoSignalEventIrul(irul, lValue)
// Signal the node with the value from the current rule
// REVIEW: THIS IS WRONG, NOT CONDITIONALLY SCHEDULING IF EVENT
#define SignalIrulSelf(irul) \
MsoDelayScheduleIrulFrom((IRUL) (irul), (irulSelf), 0)
// Signal the event with the value from the current rule
#define SignalEventIrulSelf(irul) \
MsoSignalEventIrulFrom((IRUL) (irul), (irulSelf))
// Evaluate the event after delay of 1
#define DelaySignalEventIrul(irul, lValue) \
MsoDelayScheduleIrul((irul), (lValue), 1 /* cDelay */)
// Evaluate the event after specified delay
#define DelaySignalEventIrulAfter(irul, lValue, cDelay) \
MsoDelayScheduleIrul((irul), (lValue), 1 << ((cDelay) - 1))
// Evaluate the node after delay of 1, getting value from rule
#define DelaySignalIrulSelf(irul) \
MsoDelayScheduleIrulFrom((irul), (irulSelf), 1 /* cDelay */)
// Evaluate the event after delay of 1, getting value from rule
#define DelaySignalEventIrulSelf(irul) \
MsoDelayScheduleIrulFrom((irul), (irulSelf), 1 /* cDelay */)
// Evaluate the event after delay of 1
// REVIEW daleg: OBSOLETE: USE DelaySignalEventIrul or "then ... (<event>)"
#define DelaySignalIrul(irul) \
MsoDelayScheduleIrul((irul), TRUE, 1 /* cDelay */)
// Evaluate the event after delay of 1
#define DelaySignal(rulvVar) \
DelaySignalRulv((rulvVar), TRUE)
// Evaluate the event after delay of 1
#define DelaySignalRulv(rulvVar, lValue) \
CDelaySignalRulv((rulvVar), (lValue), 1 /* cDelay */)
// Evaluate the event after delay of 1
#define CDelaySignalRulv(rulvVar, lValue, cDelay) \
MsoDelayScheduleIrul(LprulFromRulv(rulvVar)->irul, (lValue), \
(cDelay))
// Evaluate the rule after delay of 1 passing TRUE as the value
#define DelayGoToIrul1(irul) \
MsoDelayScheduleIrul((irul), TRUE, 1 /* cDelay */)
// Evaluate the rule after specified delay
#define DelayGoToIrulAfter(irul, cDelay) \
MsoDelayScheduleIrul((irul), TRUE, 1 << ((cDelay) - 1))
// Evaluate the rule with value after specified delay
#define DelayGoToIrulWithRulvAfter(irul, lValue, cDelay) \
MsoDelayScheduleIrul((irul), (lValue) - (cDelay) + 1, \
1 << ((cDelay) - 1))
// Evaluate the rule after specified delay
#define DelayGoToDirulAfter(dirul, cDelay) \
MsoDelayScheduleIrulFrom((IRUL) (irulSelf + (dirul)), (irulSelf), \
1 << ((cDelay) - 1))
// Evaluate the rule after delay of 1, incrementing value
#define DelayGoToIrulNoValue(irul) \
MsoDelayScheduleIrulFrom \
((IRUL) (irul), (IRUL) (irul), 1 /* cDelay */)
// Evaluate the rule after delay of 1, passing the value of the current node
#define DelayGoToIrul(irul) \
MsoDelayScheduleIrulFrom((IRUL) (irul), (irulSelf), 1 /* cDelay */)
// Evaluate the rule (via relative offset) after delay of 1
#define DelayGoToDirul(dirul) \
MsoDelayScheduleIrulFrom \
((IRUL) (irulSelf + (dirul)), (irulSelf), 1)
// Evaluate the rule (via relative offset) after delay of 1
#define DelayGoToDirulNoValue(dirul) \
MsoDelayScheduleIrulFrom((IRUL) (irulSelf + (dirul)), \
(IRUL) (irulSelf + (dirul)), 1)
// Evaluate the rule (via relative offset) after delay of 1, with value rulv
#define DelayGoToDirulWithRulv(dirul, rulv) \
(SetRulvOfIrul(irulSelf + (dirul), (rulv)), \
DelayGoToDirulNoValue(dirul))
// Evaluate the rule (via relative offset) after delay of 1, with value rulv2
#define DelayGoToDirulWithRulv2(dirul, rulv2) \
(SetRulv2OfIrul(irulSelf + (dirul), (short) (rulv2)), \
DelayGoToDirulNoValue(dirul))
// Evaluate the rule (via relative offset) after delay of 1, with value rulv2
#define DelayGoToDirulWithRulv1(dirul, rulv1) \
(SetRulv1OfIrul(irulSelf + (dirul), (short) (rulv1)), \
DelayGoToDirulNoValue(dirul))
// Evaluate the rule (via relative offset) after delay of 1, with values
#define DelayGoToDirulWithRulvs(dirul, rulv1, rulv2) \
(SetRulv1OfIrul(irulSelf + (dirul), (short) (rulv1)), \
SetRulv2OfIrul(irulSelf + (dirul), (short) (rulv2)), \
DelayGoToDirulNoValue(dirul))
// Deactivate curr rule if the fTest value is FALSE: used in rule test clause
#define FAutoDeactivateSelf(fTest) \
FAutoDeactivateIrul(irulSelf, (fTest))
// Deactivate the rule if the fTest value is FALSE: used in rule test clause
#define FAutoDeactivateIrul(irul, fTest) \
((fTest) ? FALSE : (_MsoFDeactivateIrul(irul), TRUE))
// Set the Rule Propagation Group to the given value
#define SetCurrRulg(rulgGroup) \
(vlpruls->rgpruldepDependents \
= vlpruls->rgrgpruldepDependents[vlpruls->rulgCurr \
= rulgGroup])
// Return the current main Rule Propagation Group
#define FCurrRulg(rulg) \
(vlpruls->rulgCurr == (rulg))
/*************************************************************************
Prototypes and macros for Debugging and Error Handling
*************************************************************************/
#ifdef DEBUG
MSOAPI_(int) MsoFTraceIrul(IRUL irul, int fTraceOn); // Trace a node
char *SzFromFixed3(long lValue, char *pchBuf); // Fixed to sz conv
#define DebugDumpQueues(wTraceLvl, sz, lValue, wToLevel) \
{ \
static const unsigned char _szDump[] = sz; \
\
_DumpQueues(wTraceLvl, _szDump, lValue, wToLevel); \
}
#define DebugDumpQueue(wTraceLvl, rulevl) \
_DumpQueue(wTraceLvl, rulevl, LplprulQueueOf(rulevl))
#else /* !DEBUG */
#define DebugDumpQueues(wTraceLvl, sz, lValue, wToLevel)
#define DebugDumpQueue(wTraceLvl, rulevl)
#endif /* DEBUG */
MSOEXTERN_C_END // ****************** End extern "C" *********************
#define EMRULE_H
#if !(defined(OFFICE_BUILD) || defined(XL))
#ifdef DYN_RULES
int FLoadDynEmRules(void); // Load dyn rulebase
#include "emruloci.h"
#endif /* DYN_RULES */
#endif /* !OFFICE_BUILD */
#endif /* !EMRULE_H */