391 lines
12 KiB
C
391 lines
12 KiB
C
/*****************************************************************************
|
|
emkwd.h
|
|
|
|
Owner: DaleG
|
|
Copyright (c) 1992-1997 Microsoft Corporation
|
|
|
|
Keyword Table header file.
|
|
|
|
*****************************************************************************/
|
|
|
|
#ifndef KWD_H
|
|
|
|
|
|
MSOEXTERN_C_BEGIN // ***************** Begin extern "C" ********************
|
|
|
|
|
|
// Limits
|
|
#define msoipkwdMax 997 // Size of keywd hash
|
|
|
|
|
|
|
|
#ifndef KWD_HASH_ONLY
|
|
|
|
// Limits...
|
|
#define msoikwdAllocMax 100 // Max num KWDs/batch
|
|
#define msoichKwdAllocMax 100 // Max # kwd chs/batch
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
Types:
|
|
|
|
kwdf Keyword-table entry record fixed.
|
|
kwd Keyword-table entry record.
|
|
kwtb Keyword table.
|
|
|
|
*************************************************************************/
|
|
|
|
|
|
#ifndef TK_DEFINED
|
|
// Definition of token type returned by lexer
|
|
typedef int TK;
|
|
|
|
#define TK_DEFINED
|
|
#endif /* !TK_DEFINED */
|
|
|
|
|
|
/* M S O K W D */
|
|
/*----------------------------------------------------------------------------
|
|
%%Structure: MSOKWD
|
|
%%Contact: daleg
|
|
|
|
Keyword-table entry record, and batch-allocation record.
|
|
----------------------------------------------------------------------------*/
|
|
|
|
// Look up as a string key value
|
|
typedef struct _MSOKWDSZ
|
|
{
|
|
const XCHAR *pxch; // String key value
|
|
short cch; // Length of kwd string
|
|
TK tk; // Token value
|
|
} MSOKWDSZ;
|
|
|
|
|
|
// Hash-table look up as a string key value
|
|
typedef struct _MSOKWD
|
|
{
|
|
const XCHAR *pxch; // String key value
|
|
short cch; // Length of kwd string
|
|
TK tk; // Token value
|
|
struct _MSOKWD *pkwdNext; // Next key in hash row
|
|
} MSOKWD;
|
|
|
|
|
|
// Batch allocation
|
|
typedef struct _MSOKWDBLK
|
|
{
|
|
struct _MSOKWDBLK *pkwdblkNext; // Next in chain
|
|
MSOKWD *pkwdRg; // Rg of MSOKWDs
|
|
} MSOKWDBLK;
|
|
|
|
|
|
// Look up as an integer key value
|
|
typedef struct _MSOKWDL
|
|
{
|
|
long lValue; // Integer key value
|
|
TK tk; // Token value
|
|
} MSOKWDL;
|
|
|
|
|
|
// Hash-table look up as a integer key value
|
|
typedef struct _MSOKWDLH
|
|
{
|
|
long lValue; // Integer key value
|
|
TK tk; // Token value
|
|
struct _MSOKWDLH *pkwdlhNext; // Next key in hash row
|
|
} MSOKWDLH;
|
|
|
|
|
|
|
|
|
|
/* M S O K W T B */
|
|
/*----------------------------------------------------------------------------
|
|
%%Structure: MSOKWTB
|
|
%%Contact: daleg
|
|
|
|
Keyword table record, and batch-allocation record.
|
|
The hash table is in rgpkwdHash. It is an array of linked lists,
|
|
of type MSOKWD.
|
|
The string buffer pxchBuf contains the character strings, PLUS the
|
|
MSOKWD records of the hash table at the end.
|
|
|
|
REVIEW: rgpkwdHash, pxchBuf and pkwdStart should be moved to the end of
|
|
this struct to avoid allocating excess space for non-hashed keytables.
|
|
Mso*Lookup* routines should assert that input MSOKWTB* arguments are of
|
|
suitable type.
|
|
----------------------------------------------------------------------------*/
|
|
|
|
typedef struct _MSOKWTB
|
|
{
|
|
// Table data
|
|
int kwtbt; // Keytable type
|
|
int ckwdMax; // Num of MSOKWD recs
|
|
MSOKWD *pkwdUnknown; // Returned when !found
|
|
void *pvTable; // Hash/Binary table
|
|
|
|
// Allocation/Init info
|
|
unsigned char fStaticInit; // Static Init-ed?
|
|
unsigned char fDynAlloced : 1; // MSOKWTB mem alloced?
|
|
unsigned char fHashTblAlloced : 1; // pvTable mem alloced?
|
|
unsigned char fSpare : 1;
|
|
|
|
// String support
|
|
XCHAR *pxchBuf; // String buffer
|
|
MSOKWD *pkwdStart; // First MSOKWD rec
|
|
|
|
// Extensions
|
|
int cxchKwdBufRemain; // Num avail chars
|
|
XCHAR *pxchKwdNext; // Next avail string
|
|
MSOKWD *pkwdNextFree; // Next av MSOKWD rec
|
|
struct _MSOKWDBLK *pkwdblkNext; // List of extra KWDs
|
|
struct _MSOKWSBLK *pkwsblkNext; // List of extra bufs
|
|
} MSOKWTB;
|
|
|
|
|
|
#define msokwtbtString 0x00
|
|
#define msokwtbtInteger 0x01
|
|
#define msokwtbtHashed 0x02
|
|
#define msokwtbtStringHashed 0x02
|
|
#define msokwtbtIntegerHashed 0x03
|
|
|
|
|
|
// String buffer batch allocation
|
|
typedef struct _MSOKWSBLK
|
|
{
|
|
struct _MSOKWSBLK *pkwsblkNext; // Next in chain
|
|
XCHAR *pxchBuf; // String buffer
|
|
} MSOKWSBLK;
|
|
|
|
|
|
/*************************************************************************
|
|
STRING LOOKUP
|
|
*************************************************************************/
|
|
|
|
// Lookup keyword
|
|
#define MsoTkLookupName(pxch, cchLen, pkwtb) \
|
|
(MsoPkwdLookupName((pxch), (cchLen), (pkwtb))->tk)
|
|
|
|
MSOAPI_(MSOKWD *) MsoPkwdLookupName( // Lookup keyword
|
|
const XCHAR *pxchStr,
|
|
int cchLen,
|
|
MSOKWTB *pkwtb
|
|
);
|
|
|
|
MSOAPI_(MSOKWD *) MsoPkwdAddTkLookupName( // Add kwd to table
|
|
const XCHAR *pxchStr,
|
|
int cchLen,
|
|
TK tk,
|
|
MSOKWTB *pkwtb,
|
|
int fCopyStr
|
|
);
|
|
|
|
MSOAPI_(int) MsoFRemoveTkLookupName( // Remove kwd from tbl
|
|
const XCHAR *pxchStr,
|
|
int cchLen,
|
|
MSOKWTB *pkwtb,
|
|
TK *ptk // RETURN
|
|
);
|
|
|
|
MSOAPI_(void) MsoInitHashKwtb(MSOKWTB *pkwtb); // Init a kwd hash tbl
|
|
|
|
MSOAPI_(MSOKWD *) _MsoPkwdNew( // Batch-alloc MSOKWDs
|
|
int ikwdMax,
|
|
MSOKWTB *pkwtb
|
|
);
|
|
|
|
int _FAddKwdRgchBuf(int ixchMax, MSOKWTB *pkwtb); // Batch-alloc kwd stzs
|
|
|
|
MSOAPI_(MSOKWTB *) MsoPkwtbNew(void); // Create new kwd tbl
|
|
|
|
#ifdef DEBUG
|
|
void _DumpKwds(MSOKWTB *pkwtb); // Print kwd table
|
|
#endif /* DEBUG */
|
|
|
|
|
|
// Get a new MSOKWD record from free list
|
|
_inline MSOKWD *MsoPkwdNew(MSOKWTB *pkwtb)
|
|
{
|
|
MSOKWD *pkwd;
|
|
|
|
return ((pkwtb)->pkwdNextFree
|
|
? (pkwd = (pkwtb)->pkwdNextFree,
|
|
(pkwtb)->pkwdNextFree = pkwd->pkwdNext,
|
|
pkwd->pkwdNext = (MSOKWD *) NULL,
|
|
pkwd)
|
|
: _MsoPkwdNew(msoikwdAllocMax, (pkwtb)));
|
|
}
|
|
|
|
// Put an existing MSOKWD record onto the free list
|
|
#define MsoDiscardPkwd(pkwd, pkwtb) \
|
|
((pkwd)->pkwdNext = (pkwtb)->pkwdNextFree, \
|
|
(pkwtb)->pkwdNextFree = (pkwd))
|
|
|
|
// Return address of first MSOKWD record for hash value in keyword lookup table
|
|
#define MsoPpkwdGetHashAddr(pkwtb, ikwd) \
|
|
(&(MsoRgpkwdHashFromKwtb(pkwtb)[ikwd]))
|
|
|
|
// Return hash table from keytable
|
|
#define MsoRgpkwdHashFromKwtb(pkwtb) \
|
|
((MSOKWD **) (pkwtb)->pvTable)
|
|
|
|
// Return integer binary table from keytable
|
|
#define MsoPkwdlFromKwtb(pkwtb) \
|
|
((MSOKWDL *) (pkwtb)->pvTable)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*************************************************************************
|
|
INTEGER LOOKUP
|
|
*************************************************************************/
|
|
|
|
// REVIEW: references to this function should become references to
|
|
// MsoPkwdlLookupL with an MSOKWTB
|
|
MSOAPI_(int) MsoWLookupKwdl( // Binary search lookup
|
|
long lValue,
|
|
MSOKWDL const *pkwdlTbl,
|
|
int ikwdlMac
|
|
);
|
|
|
|
MSOAPI_(MSOKWDL *) MsoPkwdlLookupL( // Nohash-lookup a long
|
|
long lValue,
|
|
MSOKWTB *pkwtb
|
|
);
|
|
|
|
#ifdef DEBUG
|
|
#define MsoAssertKwtb(pkwtb) \
|
|
MsoAssertKwtbSz(pkwtb, #pkwtb)
|
|
MSOAPI_(void) MsoAssertKwtbSz(MSOKWTB *pkwtb, char *szName); // Ensure sorted
|
|
#else
|
|
#define MsoAssertKwtb(pkwtb)
|
|
#endif // DEBUG
|
|
|
|
MSOAPI_(MSOKWDLH *) MsoPkwdlhLookupL( // Hash-lookup a long
|
|
long lValue,
|
|
MSOKWTB *pkwtb
|
|
);
|
|
|
|
MSOAPI_(MSOKWDLH *) MsoPkwdlhAddTkLookupL( // Add int hash lookup
|
|
long lValue,
|
|
TK tk,
|
|
MSOKWTB *pkwtb
|
|
);
|
|
|
|
MSOAPI_(MSOKWDLH *) _MsoPkwdlhNew(int ikwdMax, MSOKWTB *pkwtb);
|
|
|
|
// Return addr of first MSOKWDLH record for hash value in keyword lookup table
|
|
#define MsoPpkwdlhGetHashAddr(pkwtb, ikwd) \
|
|
(&(MsoRgpkwdlhFromKwtb(pkwtb)[ikwd]))
|
|
|
|
// Return hash table from keytable
|
|
#define MsoRgpkwdlhFromKwtb(pkwtb) \
|
|
((MSOKWDLH **) (pkwtb)->pvTable)
|
|
|
|
|
|
// Get a new MSOKWDLH record from free list
|
|
_inline MSOKWDLH *MsoPkwdlhNew(MSOKWTB *pkwtb)
|
|
{
|
|
MSOKWDLH *pkwdlh;
|
|
|
|
if (pkwtb->pkwdNextFree)
|
|
{
|
|
pkwdlh = (MSOKWDLH *) (pkwtb)->pkwdNextFree;
|
|
pkwtb->pkwdNextFree = (MSOKWD *) pkwdlh->pkwdlhNext;
|
|
pkwdlh->pkwdlhNext = (MSOKWDLH *) NULL;
|
|
return pkwdlh;
|
|
}
|
|
else
|
|
return _MsoPkwdlhNew(msoikwdAllocMax, pkwtb);
|
|
}
|
|
|
|
// Put an existing MSOKWDLH record onto the free list
|
|
#define MsoDiscardPkwdlh(pkwdlh, pkwtb) \
|
|
((pkwdlh)->pkwdlhNext = (MSOKWDLH *) (pkwtb)->pkwdNextFree, \
|
|
(pkwtb)->pkwdNextFree = (MSOKWD *) (pkwdlh))
|
|
|
|
|
|
#endif /* !KWD_HASH_ONLY */
|
|
|
|
|
|
#ifndef ANSI_XCHAR
|
|
#define MsoIpkwdHashPxch(pch, cch) MsoIpkwdHashPwch(pch, cch)
|
|
#define MsoXchUpper MsoWchToUpper
|
|
#else /* ANSI_XCHAR */
|
|
#define MsoIpkwdHashPxch(pch, cch) MsoIpkwdHashPch(pch, cch)
|
|
#define MsoXchUpper MsoChToUpper
|
|
#endif /* !ANSI_XCHAR */
|
|
|
|
|
|
|
|
/* M S O C H T O U P P E R */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: MsoChToUpper
|
|
%%Contact: daleg
|
|
|
|
Convert ANSI character to uppercase.
|
|
----------------------------------------------------------------------------*/
|
|
|
|
_inline unsigned char MsoChToUpper(unsigned char ch)
|
|
{
|
|
return (islower(ch) ? (unsigned char) toupper(ch) : ch);
|
|
}
|
|
|
|
|
|
/* M S O I P K W D H A S H P C H */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: MsoIpkwdHashPch
|
|
%%Contact: daleg
|
|
|
|
Return a hash index for the given string and length, case insensitive.
|
|
----------------------------------------------------------------------------*/
|
|
|
|
_inline int MsoIpkwdHashPch(const unsigned char *pchStr, int cchLen)
|
|
{
|
|
/* Hash on first and last character of string, ignoring case */
|
|
return ((MsoChToUpper(*pchStr) * 419)
|
|
+ (MsoChToUpper(*(pchStr + (cchLen - 1)/2)) * 467)
|
|
+ (MsoChToUpper(*(pchStr + cchLen - 1)) * 359))
|
|
% msoipkwdMax;
|
|
}
|
|
|
|
|
|
/* M S O I P K W D H A S H P W C H */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: MsoIpkwdHashPwch
|
|
%%Contact: daleg
|
|
|
|
Return a hash index for the given string and length, case insensitive.
|
|
----------------------------------------------------------------------------*/
|
|
|
|
_inline int MsoIpkwdHashPwch(const WCHAR *pwchStr, int cchLen)
|
|
{
|
|
/* Hash on first and last character of string, ignoring case */
|
|
return ((MsoWchToUpper(*pwchStr) * 419)
|
|
+ (MsoWchToUpper(*(pwchStr + (cchLen - 1)/2)) * 467)
|
|
+ (MsoWchToUpper(*(pwchStr + cchLen - 1)) * 359))
|
|
% msoipkwdMax;
|
|
}
|
|
|
|
|
|
/* M S O I P K W D L H H A S H */
|
|
/*----------------------------------------------------------------------------
|
|
%%Function: MsoIpkwdlhHash
|
|
%%Contact: daleg
|
|
|
|
Return a hash index for the given integer value.
|
|
----------------------------------------------------------------------------*/
|
|
|
|
_inline int MsoIpkwdlhHash(long lValue)
|
|
{
|
|
return (((lValue + (lValue >> 1)) & ~0x80000000) % msoipkwdMax);
|
|
}
|
|
|
|
|
|
MSOEXTERN_C_END // ****************** End extern "C" *********************
|
|
|
|
#define KWD_H
|
|
#endif /* !KWD_H */
|