static HB_PSIZE_FUNC( hb_p_pushstr ) { HB_SYMBOL_UNUSED( cargo ); return 3 + HB_PCODE_MKUSHORT( &pFunc->pCode[ nPCodePos + 1 ] ); }
/* Creates the codeblock structure * * pBuffer -> the buffer with pcodes (without HB_P_PUSHBLOCK) * wLocals -> number of local variables referenced in a codeblock * pLocalPosTable -> a table with positions on eval stack for referenced variables * pSymbols -> a pointer to the module symbol table * * Note: pLocalPosTable cannot be used if uiLocals is ZERO * */ PHB_CODEBLOCK hb_codeblockNew( const HB_BYTE * pBuffer, HB_USHORT uiLocals, const HB_BYTE * pLocalPosTable, PHB_SYMB pSymbols, HB_SIZE nLen ) { HB_STACK_TLS_PRELOAD PHB_CODEBLOCK pCBlock; PHB_ITEM pLocals, pBase; const HB_BYTE * pCode; HB_TRACE( HB_TR_DEBUG, ( "hb_codeblockNew(%p, %hu, %p, %p, %" HB_PFS "u)", pBuffer, uiLocals, pLocalPosTable, pSymbols, nLen ) ); /* * allocate memory for code block body and detach items hb_gcAllocRaw() * to be safe for automatic GC activation in hb_xgrab() without * calling hb_gcLock()/hb_gcUnlock(). [druzus] */ if( nLen ) { /* * The codeblock pcode is stored in dynamically allocated memory that * can be deallocated after creation of a codeblock. We have to duplicate * the passed buffer */ pCode = ( const HB_BYTE * ) memcpy( hb_xgrab( nLen ), pBuffer, nLen ); } else { /* * The codeblock pcode is stored in static segment. * The only allowed operation on a codeblock is evaluating it then * there is no need to duplicate its pcode - just store the pointer to it */ pCode = pBuffer; } if( uiLocals ) { /* NOTE: if a codeblock will be created by macro compiler then * uiLocal have to be ZERO * uiLocal will be also ZERO if it is a nested codeblock */ HB_USHORT ui = 1; PHB_ITEM pLocal; /* Create a table that will store the values of local variables * accessed in a codeblock * The element 0 is unused * NOTE: This table can be shared by codeblocks created during * evaluation of this codeblock */ pLocals = ( PHB_ITEM ) hb_xgrab( ( uiLocals + 1 ) * sizeof( HB_ITEM ) ); pLocals[ 0 ].type = HB_IT_NIL; do { /* Swap the current value of local variable with the reference to this * value. * TODO: If Harbour will support threads in the future then we need * to implement some kind of semaphores here. */ int iLocal = HB_PCODE_MKUSHORT( pLocalPosTable ); pLocal = hb_stackLocalVariable( iLocal ); pLocalPosTable += 2; pLocal = hb_memvarDetachLocal( pLocal ); hb_itemRawCpy( pLocals + ui, pLocal ); /* Increment the reference counter so this value will not be * released if other codeblock will be deleted */ hb_memvarValueIncRef( pLocal->item.asMemvar.value ); } while( ++ui <= uiLocals ); } else { /* Check if this codeblock is created during evaluation of another * codeblock - all inner codeblocks use the local variables table * created during creation of the outermost codeblock */ PHB_ITEM pLocal; pLocal = hb_stackSelfItem(); if( HB_IS_BLOCK( pLocal ) ) { PHB_CODEBLOCK pOwner = pLocal->item.asBlock.value; uiLocals = pOwner->uiLocals; pLocals = pOwner->pLocals; if( pLocals ) hb_xRefInc( pLocals ); } else pLocals = NULL; } pBase = hb_stackBaseItem(); pCBlock = ( PHB_CODEBLOCK ) hb_gcAllocRaw( sizeof( HB_CODEBLOCK ), &s_gcCodeblockFuncs ); pCBlock->pCode = pCode; pCBlock->dynBuffer = nLen != 0; pCBlock->pDefSymb = pBase->item.asSymbol.stackstate->uiClass ? hb_clsMethodSym( pBase ) : pBase->item.asSymbol.value; pCBlock->pSymbols = pSymbols; pCBlock->pStatics = hb_stackGetStaticsBase(); pCBlock->uiLocals = uiLocals; pCBlock->pLocals = pLocals; HB_TRACE( HB_TR_INFO, ( "codeblock created %p", pCBlock ) ); return pCBlock; }
static HB_PSIZE_FUNC( hb_p_threadstatics ) { HB_SYMBOL_UNUSED( cargo ); return 3 + ( ( HB_SIZE ) HB_PCODE_MKUSHORT( &pFunc->pCode[ nPCodePos + 1 ] ) << 1 ); }
PHB_DEBUGINFO hb_compGetDebugInfo( HB_COMP_DECL ) { PHB_DEBUGINFO pLineInfo = NULL, pInfo = NULL; HB_SIZE nPos, nSkip, nOffset; HB_ULONG ulLine; const char * pszModuleName = "", * ptr; PHB_HFUNC pFunc; pFunc = HB_COMP_PARAM->functions.pFirst; while( pFunc ) { if( ( pFunc->funFlags & HB_FUNF_FILE_DECL ) == 0 ) { nPos = ulLine = 0; while( nPos < pFunc->nPCodePos ) { nSkip = 0; switch( pFunc->pCode[ nPos ] ) { case HB_P_LINE: ulLine = HB_PCODE_MKUSHORT( &pFunc->pCode[ nPos + 1 ] ); break; case HB_P_MODULENAME: pszModuleName = ( const char * ) &pFunc->pCode[ nPos + 1 ]; pInfo = NULL; break; /* * This enables checking also code block bodies, * if it's not necessary then simply remove the * code below. [druzus] */ case HB_P_PUSHBLOCKLARGE: nSkip = 8 + HB_PCODE_MKUSHORT( &pFunc->pCode[ nPos + 6 ] ) * 2; break; case HB_P_PUSHBLOCK: nSkip = 7 + HB_PCODE_MKUSHORT( &pFunc->pCode[ nPos + 5 ] ) * 2; break; case HB_P_PUSHBLOCKSHORT: nSkip = 2; break; } if( ulLine != 0 ) { if( ! pInfo ) { int i; ptr = strrchr( pszModuleName, ':' ); i = ptr ? ( int ) ( ptr - pszModuleName ) : ( int ) strlen( pszModuleName ); pInfo = pLineInfo; while( pInfo != NULL ) { if( strncmp( pszModuleName, pInfo->pszModuleName, i ) == 0 && ( pInfo->pszModuleName[ i ] == '\0' || pInfo->pszModuleName[ i ] == ':' ) ) break; pInfo = pInfo->pNext; } if( ! pInfo ) { pInfo = ( PHB_DEBUGINFO ) hb_xgrab( sizeof( HB_DEBUGINFO ) ); pInfo->pszModuleName = hb_strndup( pszModuleName, i ); pInfo->ulFirstLine = pInfo->ulLastLine = ulLine; /* * allocate memory in 256 bytes chunks (for 2048 lines) * The last 1 byte is reserved for additional 0 byte if * the caller will want to use the returned buffer as * parameter to hb_compGenPushString(). [druzus] */ pInfo->ulAllocated = ( ( ulLine >> 3 ) + 0x100 ) & 0xFFFFFF00L; pInfo->pLineMap = ( HB_BYTE * ) hb_xgrab( pInfo->ulAllocated + 1 ); memset( pInfo->pLineMap, 0, pInfo->ulAllocated + 1 ); pInfo->pNext = pLineInfo; pLineInfo = pInfo; } } nOffset = ulLine >> 3; if( pInfo->ulAllocated <= nOffset ) { HB_ULONG ulNewSize = ( ( ulLine >> 3 ) + 0x100 ) & 0xFFFFFF00L; pInfo->pLineMap = ( HB_BYTE * ) hb_xrealloc( pInfo->pLineMap, ulNewSize + 1 ); memset( pInfo->pLineMap + pInfo->ulAllocated, 0, ulNewSize - pInfo->ulAllocated + 1 ); pInfo->ulAllocated = ulNewSize; } pInfo->pLineMap[ nOffset ] |= 1 << ( ulLine & 0x7 ); /* * It's possible the the line number will be ascending * if some external file is included more then once. [druzus] */ if( pInfo->ulFirstLine > ulLine ) pInfo->ulFirstLine = ulLine; if( pInfo->ulLastLine < ulLine ) pInfo->ulLastLine = ulLine; ulLine = 0; }