Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

417 lines
7.8 KiB

//
// Copyright (c) Microsoft Corporation 1995
//
// symtab.c
//
// This file contains the symbol table functions.
//
// History:
// 04-30-95 ScottH Created
//
#include "proj.h"
#define SYMTAB_SIZE_GROW 10 // in elements
//
// Symbol table entry routines
//
/*----------------------------------------------------------
Purpose: Create a symbol table entry
Returns: RES_OK
RES_E_OUTOFMEMORY
RES_E_INVALIDPARAM
Cond: --
*/
RES PUBLIC STE_Create(
PSTE * ppste,
LPCSTR pszIdent,
DATATYPE dt)
{
RES res;
PSTE pste;
ASSERT(ppste);
ASSERT(pszIdent);
pste = GAllocType(STE);
if (pste)
{
res = RES_OK; // assume success
if ( !GSetString(&pste->pszIdent, pszIdent) )
res = RES_E_OUTOFMEMORY;
else
{
pste->dt = dt;
}
}
else
res = RES_E_OUTOFMEMORY;
// Did anything above fail?
if (RFAILED(res))
{
// Yes; clean up
STE_Destroy(pste);
pste = NULL;
}
*ppste = pste;
return res;
}
/*----------------------------------------------------------
Purpose: Destroy the STE element
Returns: --
Cond: --
*/
void CALLBACK STE_DeletePAPtr(
LPVOID pv,
LPARAM lparam)
{
STE_Destroy(pv);
}
/*----------------------------------------------------------
Purpose: Destroys symbol table entry
Returns: RES_OK
RES_E_INVALIDPARAM
Cond: --
*/
RES PUBLIC STE_Destroy(
PSTE this)
{
RES res;
if (this)
{
if (this->pszIdent)
GSetString(&this->pszIdent, NULL); // free
// (The evalres field should not be freed. It is
// a copy from somewhere else.)
GFree(this);
res = RES_OK;
}
else
res = RES_E_INVALIDPARAM;
return res;
}
/*----------------------------------------------------------
Purpose: Retrieves the symbol table entry value. The type
depends on the datatype.
Returns: RES_OK
RES_E_FAIL (for a type that does not have a value)
RES_E_INVALIDPARAM
Cond: --
*/
RES PUBLIC STE_GetValue(
PSTE this,
PEVALRES per)
{
RES res;
ASSERT(this);
ASSERT(per);
if (this && per)
{
res = RES_OK; // assume success
switch (this->dt)
{
case DATA_INT:
case DATA_BOOL:
case DATA_STRING:
case DATA_LABEL:
case DATA_PROC:
per->dw = this->er.dw;
break;
default:
ASSERT(0);
res = RES_E_FAIL;
break;
}
}
else
res = RES_E_INVALIDPARAM;
return res;
}
//
// Symbol Table functions
//
/*----------------------------------------------------------
Purpose: Creates a symbol table
Returns: RES_OK
RES_E_OUTOFMEMORY
RES_E_INVALIDPARAM
Cond: --
*/
RES PUBLIC Symtab_Create(
PSYMTAB * ppst,
PSYMTAB pstNext) // May be NULL
{
RES res;
PSYMTAB pst;
ASSERT(ppst);
pst = GAllocType(SYMTAB);
if (pst)
{
if (PACreate(&pst->hpaSTE, SYMTAB_SIZE_GROW))
{
pst->pstNext = pstNext;
res = RES_OK;
}
else
res = RES_E_OUTOFMEMORY;
}
else
res = RES_E_INVALIDPARAM;
// Did anything above fail?
if (RFAILED(res) && pst)
{
// Yes; clean up
Symtab_Destroy(pst);
pst = NULL;
}
*ppst = pst;
return res;
}
/*----------------------------------------------------------
Purpose: Destroys a symbol table
Returns: RES_OK
RES_E_INVALIDPARAM
Cond: --
*/
RES PUBLIC Symtab_Destroy(
PSYMTAB this)
{
RES res;
if (this)
{
if (this->hpaSTE)
{
PADestroyEx(this->hpaSTE, STE_DeletePAPtr, 0);
}
GFree(this);
res = RES_OK;
}
else
res = RES_E_INVALIDPARAM;
return res;
}
/*----------------------------------------------------------
Purpose: Compare symbol table entries by name.
Returns:
Cond: --
*/
int CALLBACK Symtab_Compare(
LPVOID pv1,
LPVOID pv2,
LPARAM lParam)
{
PSTE pste1 = pv1;
PSTE pste2 = pv2;
return lstrcmpi(pste1->pszIdent, pste2->pszIdent);
}
/*----------------------------------------------------------
Purpose: Looks for pszIdent in the symbol table entry.
If STFF_IMMEDIATEONLY is not set, this function will
look in successive scopes if the symbol is not found
within this immediate scope.
Symbol table entry is returned in *psteOut.
Returns: RES_OK (if found)
RES_FALSE (if not found)
RES_E_INVALIDPARAM
Cond: --
*/
RES PUBLIC Symtab_FindEntry(
PSYMTAB this,
LPCSTR pszIdent,
DWORD dwFlags,
PSTE * ppsteOut, // May be NULL
PSYMTAB * ppstScope) // May be NULL
{
RES res;
// Default return values to NULL
if (ppsteOut)
*ppsteOut = NULL;
if (ppstScope)
*ppstScope = NULL;
if (this && pszIdent)
{
DWORD iste;
STE ste;
// Peform a binary search. Find a match?
ste.pszIdent = (LPSTR)pszIdent;
iste = PASearch(this->hpaSTE, &ste, 0, Symtab_Compare, (LPARAM)this, PAS_SORTED);
if (PA_ERR != iste)
{
// Yes
PSTE pste = PAFastGetPtr(this->hpaSTE, iste);
if (ppsteOut)
*ppsteOut = pste;
if (ppstScope)
*ppstScope = this;
res = RES_OK;
}
// Check other scopes?
else if (IsFlagClear(dwFlags, STFF_IMMEDIATEONLY) && this->pstNext)
{
// Yes
res = Symtab_FindEntry(this->pstNext, pszIdent, dwFlags, ppsteOut, ppstScope);
}
else
res = RES_FALSE;
}
else
res = RES_E_INVALIDPARAM;
return res;
}
/*----------------------------------------------------------
Purpose: Insert the given symbol table entry into the symbol
table. This function does not prevent duplicate symbols.
Returns: RES_OK
RES_E_OUTOFMEMORY
Cond: --
*/
RES PUBLIC Symtab_InsertEntry(
PSYMTAB this,
PSTE pste)
{
RES res;
ASSERT(this);
ASSERT(pste);
if (PAInsertPtr(this->hpaSTE, PA_APPEND, pste))
{
PASort(this->hpaSTE, Symtab_Compare, (LPARAM)this);
res = RES_OK;
}
else
res = RES_E_OUTOFMEMORY;
return res;
}
/*----------------------------------------------------------
Purpose: This function generates a unique label name.
Returns: RES_OK
RES_INVALIDPARAM
Cond: Caller must free *ppszIdent.
*/
RES PUBLIC Symtab_NewLabel(
PSYMTAB this,
LPSTR pszIdentBuf) // must be size MAX_BUF_KEYWORD
{
static int s_nSeed = 0;
#pragma data_seg(DATASEG_READONLY)
const static char c_szLabelPrefix[] = "__ssh%u";
#pragma data_seg()
RES res;
char sz[MAX_BUF_KEYWORD];
PSTE pste;
ASSERT(pszIdentBuf);
do
{
// Generate name
wsprintf(sz, c_szLabelPrefix, s_nSeed++);
// Is this unique?
res = Symtab_FindEntry(this, sz, STFF_DEFAULT, NULL, NULL);
if (RES_FALSE == res)
{
// Yes
res = STE_Create(&pste, sz, DATA_LABEL);
if (RSUCCEEDED(res))
{
res = Symtab_InsertEntry(this, pste);
if (RSUCCEEDED(res))
{
lstrcpyn(pszIdentBuf, sz, MAX_BUF_KEYWORD);
res = RES_FALSE; // break out of this loop
}
}
}
}
while(RES_OK == res);
if (RES_FALSE == res)
res = RES_OK;
return res;
}