PHB_DYNS hb_dynsymGetWithNamespaces( const char * szName, const char * pNamespaces ) /* finds and creates a symbol if not found CASE INSENSITIVE! */ { HB_THREAD_STUB_STACK PHB_DYNS pDynSym; HB_TRACE( HB_TR_DEBUG, ( "hb_dynsymGetCase(%s)", szName ) ); /* TraceLog( NULL, "Searching: %s\n", szName ); */ /* JC1: read the notice for hb_dynsymGet() */ hb_dynsymLock(); pDynSym = hb_dynsymFindNameWithNamespaces( szName, pNamespaces ); if( ! pDynSym ) /* Does it exists ? */ { /* TraceLog( NULL, "Creating: %s\n", szName ); */ pDynSym = hb_dynsymNew( hb_symbolNew( szName ), HB_GETMODULESYM() ); /* Make new symbol */ pDynSym->pSymbol->scope.value = HB_FS_PUBLIC; } hb_dynsymUnlock(); /* TraceLog( NULL, "Returning: %p\n", pDynSym ); */ return pDynSym; }
PHB_DYNS hb_dynsymFindName_r( const char * szName, PHB_DYNS pDest ) { PHB_DYNS pRet; hb_dynsymLock(); pRet = hb_dynsymFindName( szName ); if( pRet ) { HB_MEMCPY( pDest, pRet, sizeof( HB_DYNS ) ); hb_dynsymUnlock(); return pDest; } hb_dynsymUnlock(); return NULL; }
PHB_DYNS hb_dynsymNew_r( PHB_SYMB pSymbol, PSYMBOLS pModuleSymbols, PHB_DYNS pDest ) { PHB_DYNS pRet; hb_dynsymLock(); pRet = hb_dynsymNew( pSymbol, pModuleSymbols ); if( pRet ) { HB_MEMCPY( pDest, pRet, sizeof( HB_DYNS ) ); hb_dynsymUnlock(); return pDest; } hb_dynsymUnlock(); return NULL; }
PHB_DYNS hb_dynsymGetCase_r( const char * szName, PHB_DYNS pDest ) { PHB_DYNS pRet; hb_dynsymLock(); pRet = hb_dynsymGetCase( szName ); if ( pRet ) { memcpy( pDest, pRet, sizeof( HB_DYNS ) ); hb_dynsymUnlock(); return pDest; } hb_dynsymUnlock(); return NULL; }
/* NOT TESTED YET!!! */ PHB_DYNS hb_dynsymPos( USHORT uiPos ) { PHB_DYNS ret = NULL; hb_dynsymLock(); if( ( UINT ) uiPos < s_uiDynSymbols ) ret = s_pDynItems[ uiPos ].pDynSym; hb_dynsymUnlock(); return ret; }
PHB_DYNS hb_dynsymGet( const char * szName ) /* finds and creates a symbol if not found */ { HB_THREAD_STUB_STACK /* make a copy as we may get a const string, then turn it to uppercase */ char szUprName[ HB_SYMBOL_NAME_LEN + 1 ]; PHB_DYNS pDynSym; HB_TRACE( HB_TR_DEBUG, ( "hb_dynsymGet(%s)", szName ) ); { register int iLen = HB_SYMBOL_NAME_LEN; char * pDest = szUprName; do { register char cChar = *szName++; if( cChar == 0 || cChar == ' ' || cChar == '\t' ) break; else if( cChar >= 'a' && cChar <= 'z' ) *pDest++ = cChar - ( 'a' - 'A' ); else *pDest++ = cChar; } while( --iLen ); *pDest = '\0'; } /* JC1: Notice, locking this function MAY seem useless but it is not. Suppose two threads calling this functon with the same szUprName: both of them may find ! pDynSym, and both of them may proceed to hb_dynsymNew(). Although this operation would suceed, one of the threas would get an invalid reference, and we would have a memory leak, as one of the two dynsymNew() would be overriden */ hb_dynsymLock(); pDynSym = hb_dynsymFind( ( char * ) szUprName ); if( ! pDynSym ) /* Does it exists ? */ { /* TraceLog( NULL, "*** Did NOT find >%s< - CREATED New!\n", szUprName ); */ pDynSym = hb_dynsymNew( hb_symbolNew( ( char * ) szUprName ), HB_GETMODULESYM() ); /* Make new symbol */ pDynSym->pSymbol->scope.value = HB_FS_PUBLIC; } hb_dynsymUnlock(); return pDynSym; }
void hb_dynsymLog( void ) { /* HB_THREAD_STUB */ register UINT uiPos; HB_TRACE( HB_TR_DEBUG, ( "hb_dynsymLog()" ) ); hb_dynsymLock(); for( uiPos = 0; uiPos < s_uiDynSymbols; uiPos++ ) /* For all dynamic symbols */ printf( "%i %s\n", uiPos + 1, s_pDynItems[ uiPos ].pDynSym->pSymbol->szName ); hb_dynsymUnlock(); }
UINT hb_dynsymEval( PHB_DYNS_FUNC pFunction, void * Cargo ) { register UINT uiPos; BOOL bCont = TRUE; HB_TRACE( HB_TR_DEBUG, ( "hb_dynsymEval(%p, %p)", pFunction, Cargo ) ); hb_dynsymLock(); for( uiPos = 0; uiPos < s_uiDynSymbols && bCont; uiPos++ ) bCont = ( pFunction ) ( s_pDynItems[ uiPos ].pDynSym, Cargo ); hb_dynsymUnlock(); return uiPos; }
PHB_DYNS hb_dynsymFind( const char * szName ) { HB_THREAD_STUB HB_TRACE( HB_TR_DEBUG, ( "hb_dynsymFind(%s)", szName ) ); hb_dynsymLock(); if( s_pDynItems == NULL ) { s_pDynItems = ( PDYNHB_ITEM ) hb_xgrab( sizeof( DYNHB_ITEM ) ); /* Grab array */ s_pDynItems->pDynSym = ( PHB_DYNS ) hb_xgrab( sizeof( HB_DYNS ) ); /* Always grab a first symbol. Never an empty bucket. *<1>* */ memset( s_pDynItems->pDynSym, 0, sizeof( HB_DYNS ) ); hb_dynsymUnlock(); return NULL; } else { /* Classic Tree Insert Sort Mechanism * * Insert Sort means the new item is entered alphabetically into * the array. In this case s_pDynItems ! * * 1) We start in the middle of the array. * 2a) If the symbols are equal -> we have found the symbol !! * Champagne ! We're done. * b) If the symbol we are looking for ('ge') is greater than the * middle ('po'), we start looking left. * Only the first part of the array is going to be searched. * Go to (1) * c) If the symbol we are looking for ('ge') is smaller than the * middle ('ko'), we start looking right * Only the last part of the array is going to be searched. * Go to (1) */ UINT uiFirst = 0; UINT uiLast = s_uiDynSymbols; UINT uiMiddle = uiLast / 2; int iCmp; s_uiClosestDynSym = uiMiddle; /* Start in the middle */ while( uiFirst < uiLast ) { iCmp = strcmp( s_pDynItems[ uiMiddle ].pDynSym->pSymbol->szName, szName ); if( iCmp == 0 ) { PHB_DYNS pDynSym = s_pDynItems[ uiMiddle ].pDynSym; s_uiClosestDynSym = uiMiddle; hb_dynsymUnlock(); return pDynSym; } else if( iCmp < 0 ) { uiLast = uiMiddle; s_uiClosestDynSym = uiMiddle; } else /* if( iCmp > 0 ) */ { uiFirst = uiMiddle + 1; s_uiClosestDynSym = uiFirst; } uiMiddle = uiFirst + ( ( uiLast - uiFirst ) / 2 ); } } #ifdef HB_SYMLIMIT_10_WORKAROUND /* * (c) 2002, Marcelo Lombardo <*****@*****.**> * This is an emulation workaround for the symbol table limited to 10 chars, * since the build flag -DHB_SYMBOL_NAME_LEN=10 is not an option anymore. */ if( s_uiClosestDynSym < s_uiDynSymbols ) { USHORT iLen1 = strlen( szName ); USHORT iLen2 = strlen( s_pDynItems[ s_uiClosestDynSym ].pDynSym->pSymbol->szName ); BOOL bOk = 1; USHORT uiPos; /* * Let's check the closer symbol found. This code compares each char in the smallest symbol * name to the largest symbol name, if both are larger than 10. */ if( iLen1 >= 10 && iLen2 >= 10 && ( ! ( iLen1 == iLen2 && iLen1 == 10 ) ) ) { if( iLen1 > iLen2 ) { for( uiPos = 0; uiPos < iLen2; uiPos++ ) { if( szName[ uiPos ] != s_pDynItems[ s_uiClosestDynSym ].pDynSym->pSymbol->szName[ uiPos ] ) { bOk = 0; break; } } } else if( iLen2 > iLen1 ) { for( uiPos = 0; uiPos < iLen1; uiPos++ ) { if( szName[ uiPos ] != s_pDynItems[ s_uiClosestDynSym ].pDynSym->pSymbol->szName[ uiPos ] ) { bOk = 0; break; } } } else if( iLen1 == iLen2 ) bOk = 0; if( bOk ) { PHB_DYNS pDynSym = s_pDynItems[ s_uiClosestDynSym ].pDynSym; hb_dynsymUnlock(); return pDynSym; } } /* * We did not find the symbol, but "nCount" looks closer to the tree search * than "nCountDial", when searching for "nCountDialog". So our best chance * is to cut off szName up to 10 chars and redo the search. */ if( iLen1 > 10 && iLen2 < 10 ) { USHORT uiFirst = 0; USHORT uiLast = s_uiDynSymbols; USHORT uiMiddle = uiLast / 2; char szNameLimited[ 10 + 1 ]; char * pDest = szNameLimited; iLen1 = 10; pDest[ iLen1 ] = '\0'; while( iLen1-- ) *pDest++ = *szName++; s_uiClosestDynSym = uiMiddle; /* Start in the middle */ while( uiFirst < uiLast ) { int iCmp = strcmp( s_pDynItems[ uiMiddle ].pDynSym->pSymbol->szName, szNameLimited ); if( iCmp == 0 ) { PHB_DYNS pDynSym = s_pDynItems[ uiMiddle ].pDynSym; s_uiClosestDynSym = uiMiddle; hb_dynsymUnlock(); return pDynSym; } else if( iCmp < 0 ) { uiLast = uiMiddle; s_uiClosestDynSym = uiMiddle; } else /* if( iCmp > 0 ) */ { uiFirst = uiMiddle + 1; s_uiClosestDynSym = uiFirst; } uiMiddle = uiFirst + ( ( uiLast - uiFirst ) / 2 ); } } /* * In other hand, if szName has 10 chars and the Symbol table contains a similar * entry, s_uiClosestDynSym may be wrong. * For instance, if we search for "cAliasRela", but in the symbol table we have * "cAliasRelac" and "cAliasNiv", the tree schema returns the wrong entry as the * closest ("cAliasNiv"). The best solution in this case is to complete szName * with some trailing chars ( "_" ), and redo the process. */ if( iLen1 == 10 && iLen2 < 10 ) { USHORT uiFirst = 0; USHORT uiLast = s_uiDynSymbols; USHORT uiMiddle = uiLast / 2; USHORT iuCount; char szNameExtended[ 10 + 8 ]; char * pDest = szNameExtended; pDest[ 17 ] = '\0'; for( iuCount = 0; iuCount < 17; iuCount++ ) { if( iuCount < 10 ) pDest[ iuCount ] = szName[ iuCount ]; else pDest[ iuCount ] = '_'; } s_uiClosestDynSym = uiMiddle; /* Start in the middle */ while( uiFirst < uiLast ) { int iCmp = strcmp( s_pDynItems[ uiMiddle ].pDynSym->pSymbol->szName, szNameExtended ); if( iCmp == 0 ) { PHB_DYNS pDynSym = s_pDynItems[ uiMiddle ].pDynSym; s_uiClosestDynSym = uiMiddle; hb_dynsymUnlock(); return pDynSym; } else if( iCmp < 0 ) { uiLast = uiMiddle; s_uiClosestDynSym = uiMiddle; } else /* if( iCmp > 0 ) */ { uiFirst = uiMiddle + 1; s_uiClosestDynSym = uiFirst; } uiMiddle = uiFirst + ( ( uiLast - uiFirst ) / 2 ); } iLen1 = strlen( szName ); iLen2 = strlen( s_pDynItems[ s_uiClosestDynSym ].pDynSym->pSymbol->szName ); bOk = 1; if( iLen2 > 10 ) { for( uiPos = 0; uiPos < iLen1; uiPos++ ) { if( szName[ uiPos ] != s_pDynItems[ s_uiClosestDynSym ].pDynSym->pSymbol->szName[ uiPos ] ) { bOk = 0; break; } } if( bOk ) { PHB_DYNS pDynSym = s_pDynItems[ s_uiClosestDynSym ].pDynSym; hb_dynsymUnlock(); return pDynSym; } } } } #endif hb_dynsymUnlock(); return NULL; }
PHB_DYNS hb_dynsymNew( PHB_SYMB pSymbol, PSYMBOLS pModuleSymbols ) /* creates a new dynamic symbol */ { HB_THREAD_STUB PHB_DYNS pDynSym; HB_TRACE( HB_TR_DEBUG, ( "hb_dynsymNew(%p, %p)", pSymbol, pModuleSymbols ) ); hb_dynsymLock(); pDynSym = hb_dynsymFind( pSymbol->szName ); /* Find position */ if( pDynSym ) /* If name exists */ { assert( 0 ); if( ( pSymbol->scope.value & HB_FS_LOCAL ) == HB_FS_LOCAL ) { #if 0 assert( pModuleSymbols ); if( pDynSym->pModuleSymbols ) TraceLog( NULL, "Symbol: '%s' was previously defined at Module: '%s'\n", pSymbol->szName, pDynSym->pModuleSymbols->szModuleName ); #endif /* if( pSymbol->value.pFunPtr && pDynSym->pSymbol->value.pFunPtr == NULL ) */ { #if 0 /* reenabled - it's still wrong, Druzus */ /* see note below */ /* register only non static functions */ if( ( pSymbol->scope.value & ( HB_FS_STATIC | HB_FS_INITEXIT ) ) == HB_FS_STATIC ) { assert( 0 ); TraceLog( NULL, "Rejecting: %s in %s\n", pSymbol->szName, pModuleSymbols ? pModuleSymbols->szModuleName : "" ); } else #endif { /* This is the symbol of the function definition module. */ assert( pSymbol->value.pFunPtr ); pDynSym->pSymbol = pSymbol; } } pDynSym->pModuleSymbols = pModuleSymbols; /* TraceLog( NULL, "Symbol: '%s' DEFINED in Module: '%s'\n", pSymbol->szName, pModuleSymbols ? pModuleSymbols->szModuleName : "" ); */ } pSymbol->pDynSym = pDynSym; /* place a pointer to DynSym */ hb_dynsymUnlock(); return pDynSym; /* Return pointer to DynSym */ } if( s_uiDynSymbols == 0 ) /* Do we have any symbols ? */ { pDynSym = s_pDynItems[ 0 ].pDynSym; /* Point to first symbol */ /* *<1>* Remember we already got this one */ } else /* We want more symbols ! */ { s_pDynItems = ( PDYNHB_ITEM ) hb_xrealloc( s_pDynItems, ( s_uiDynSymbols + 1 ) * sizeof( DYNHB_ITEM ) ); if( s_uiClosestDynSym <= s_uiDynSymbols ) /* Closest < current !! */ { /* Here it goes :-) */ register UINT uiPos; for( uiPos = 0; uiPos < ( UINT ) ( s_uiDynSymbols - s_uiClosestDynSym ); uiPos++ ) { /* Insert element in array */ HB_MEMCPY( &s_pDynItems[ s_uiDynSymbols - uiPos ], &s_pDynItems[ s_uiDynSymbols - uiPos - 1 ], sizeof( DYNHB_ITEM ) ); } } pDynSym = ( PHB_DYNS ) hb_xgrab( sizeof( HB_DYNS ) ); s_pDynItems[ s_uiClosestDynSym ].pDynSym = pDynSym; /* Enter DynSym */ } s_uiDynSymbols++; /* Got one more symbol */ pDynSym->hMemvar = 0; pDynSym->hArea = 0; #ifndef HB_NO_PROFILER pDynSym->ulCalls = 0; /* profiler support */ pDynSym->ulTime = 0; /* profiler support */ pDynSym->ulRecurse = 0; #endif #if 0 /* now the compiler creates separate symbols for functions and * fields/memvars/aliases so we should not have any problem here * and this code is not necessary but I decide to left it here * disabled at least for debugging. */ if( pSymbol->value.pFunPtr && ( pSymbol->scope.value & ( HB_FS_STATIC | HB_FS_INITEXIT ) ) == HB_FS_STATIC ) { /* * This symbol points to static function - we cannot register * such symbols in global dynsyms because we may have more * static functions with the same name and non static one * registered later - the static function should be directly * accessible _ONLY_ from their modules. * So we will clone this symbol. */ assert( 0 ); TraceLog( NULL, "Cloned: %s in %s\n", pSymbol->szName, pModuleSymbols ? pModuleSymbols->szModuleName : "" ); pSymbol->pDynSym = pDynSym; /* place a pointer to DynSym in original symbol */ pSymbol = hb_symbolNew( pSymbol->szName ); /* clone the symbol */ } #endif /* TraceLog( NULL, "Symbol: '%s' IMPORTED in Module: '%s'\n", pSymbol->szName, pModuleSymbols ? pModuleSymbols->szModuleName : "" ); */ if( ( pSymbol->scope.value & HB_FS_LOCAL ) == HB_FS_LOCAL ) { /* This is the true local symbol */ assert( pSymbol->value.pFunPtr ); assert( pModuleSymbols ); pDynSym->pModuleSymbols = pModuleSymbols; /* TraceLog( NULL, "Symbol: '%s' DEFINED in Module: '%s'\n", pSymbol->szName, pModuleSymbols ? pModuleSymbols->szModuleName : "" ); */ } else { pDynSym->pModuleSymbols = NULL; } pDynSym->pSymbol = pSymbol; pSymbol->pDynSym = pDynSym; /* place a pointer to DynSym */ hb_dynsymUnlock(); return pDynSym; }