418 lines
7.8 KiB
C
418 lines
7.8 KiB
C
|
//
|
||
|
// 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;
|
||
|
}
|
||
|
|
||
|
|
||
|
|