PageRenderTime 50ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/harbour-3.0.0/src/debug/dbgentry.c

#
C | 1769 lines | 1394 code | 308 blank | 67 comment | 257 complexity | f6098a8e28dae8cfe992f628d25d6eec MD5 | raw file
Possible License(s): AGPL-1.0, BSD-3-Clause, CC-BY-SA-3.0, LGPL-3.0, GPL-2.0, LGPL-2.0, LGPL-2.1
  1. /*
  2. * $Id: dbgentry.c 14827 2010-06-19 14:26:56Z vszakats $
  3. */
  4. /*
  5. * xHarbour Project source code:
  6. * Debugger entry routine
  7. *
  8. * Copyright 2005 Phil Krylov <phil a t newstar.rinet.ru>
  9. * www - http://www.xharbour.org
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2, or (at your option)
  14. * any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this software; see the file COPYING. If not, write to
  23. * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  24. * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
  25. *
  26. * As a special exception, xHarbour license gives permission for
  27. * additional uses of the text contained in its release of xHarbour.
  28. *
  29. * The exception is that, if you link the xHarbour libraries with other
  30. * files to produce an executable, this does not by itself cause the
  31. * resulting executable to be covered by the GNU General Public License.
  32. * Your use of that executable is in no way restricted on account of
  33. * linking the xHarbour library code into it.
  34. *
  35. * This exception does not however invalidate any other reasons why
  36. * the executable file might be covered by the GNU General Public License.
  37. *
  38. * This exception applies only to the code released with this xHarbour
  39. * explicit exception. If you add/copy code from other sources,
  40. * as the General Public License permits, the above exception does
  41. * not apply to the code that you add in this way. To avoid misleading
  42. * anyone as to the status of such modified files, you must delete
  43. * this exception notice from them.
  44. *
  45. * If you write modifications of your own for xHarbour, it is your choice
  46. * whether to permit this exception to apply to your modifications.
  47. * If you do not wish that, delete this exception notice.
  48. *
  49. */
  50. #include "hbapidbg.h"
  51. #include "hbapiitm.h"
  52. #include "hbapicls.h"
  53. #include "hbapirdd.h"
  54. #include "hbstack.h"
  55. #include "hbvm.h"
  56. #include "hbthread.h"
  57. #include "hbdebug.ch"
  58. #include "hbmacro.ch"
  59. /* dummy function declaration */
  60. static HB_BOOL hb_clsSetScope( HB_BOOL fScope ) { return fScope; }
  61. #define HB_DBGINFO_DISABLE ( ( HB_DEBUGINFO * ) ( HB_PTRDIFF ) 0x01 )
  62. #if defined( HB_OS_UNIX )
  63. #define FILENAME_EQUAL( s1, s2 ) ( ! strcmp( ( s1 ), ( s2 ) ) )
  64. #else
  65. #define FILENAME_EQUAL( s1, s2 ) ( ! hb_stricmp( ( s1 ), ( s2 ) ) )
  66. #endif
  67. #define ARRAY_ADD( type, array, length ) \
  68. ( ( ++length == 1 ) ? ( array = ( type * ) hb_xgrab( sizeof( type ) ) ) : \
  69. ( ( array = ( type * ) hb_xrealloc( array, sizeof( type ) * length ) ) + \
  70. length - 1 ) )
  71. #define ARRAY_DEL( type, array, length, index ) \
  72. do { \
  73. if( !--length ) \
  74. hb_xfree( array ); \
  75. else if( index < length ) \
  76. memmove( array + index, array + index + 1, sizeof( type ) * ( length - index ) ); \
  77. } while( 0 )
  78. #if 1
  79. # define HB_DBGCOMMON_LOCK hb_threadEnterCriticalSection( &s_dbgMtx );
  80. # define HB_DBGCOMMON_UNLOCK hb_threadLeaveCriticalSection( &s_dbgMtx );
  81. static HB_CRITICAL_NEW( s_dbgMtx );
  82. #else
  83. # define HB_DBGCOMMON_LOCK
  84. # define HB_DBGCOMMON_UNLOCK
  85. #endif
  86. typedef struct
  87. {
  88. char * szModule;
  89. int nLine;
  90. char * szFunction;
  91. } HB_BREAKPOINT;
  92. typedef struct
  93. {
  94. int nIndex;
  95. PHB_ITEM xValue;
  96. } HB_TRACEPOINT;
  97. typedef struct
  98. {
  99. char * szName;
  100. char cType;
  101. union
  102. {
  103. int num;
  104. PHB_ITEM ptr;
  105. } frame;
  106. int nIndex;
  107. } HB_VARINFO;
  108. typedef struct
  109. {
  110. char * szExpr;
  111. PHB_ITEM pBlock;
  112. int nVars;
  113. char ** aVars;
  114. HB_VARINFO * aScopes;
  115. } HB_WATCHPOINT;
  116. typedef struct
  117. {
  118. char * szModule;
  119. char * szFunction;
  120. int nLine;
  121. int nProcLevel;
  122. int nLocals;
  123. HB_VARINFO * aLocals;
  124. int nStatics;
  125. HB_VARINFO * aStatics;
  126. } HB_CALLSTACKINFO;
  127. typedef struct
  128. {
  129. char * szModule;
  130. int nStatics;
  131. HB_VARINFO * aStatics;
  132. int nGlobals;
  133. HB_VARINFO * aGlobals;
  134. int nExternGlobals;
  135. HB_VARINFO * aExternGlobals;
  136. } HB_MODULEINFO;
  137. typedef struct
  138. {
  139. int nModules;
  140. HB_MODULEINFO * aModules;
  141. PHB_ITEM pStopLines;
  142. } HB_DBGCOMMONINFO;
  143. typedef struct
  144. {
  145. HB_BOOL bQuit;
  146. HB_BOOL bGo;
  147. HB_BOOL bInside;
  148. int nBreakPoints;
  149. HB_BREAKPOINT * aBreak;
  150. int nTracePoints;
  151. HB_TRACEPOINT * aTrace;
  152. int nWatchPoints;
  153. HB_WATCHPOINT * aWatch;
  154. HB_BOOL bTraceOver;
  155. int nTraceLevel;
  156. HB_BOOL bNextRoutine;
  157. HB_BOOL bCodeBlock;
  158. HB_BOOL bToCursor;
  159. int nToCursorLine;
  160. char * szToCursorModule;
  161. int nProcLevel;
  162. int nCallStackLen;
  163. HB_CALLSTACKINFO * aCallStack;
  164. HB_BOOL bCBTrace;
  165. HB_BOOL ( *pFunInvoke )( void );
  166. HB_BOOL bInitGlobals;
  167. HB_BOOL bInitStatics;
  168. HB_BOOL bInitLines;
  169. } HB_DEBUGINFO;
  170. static HB_DBGCOMMONINFO s_common = { 0, NULL, NULL };
  171. static PHB_ITEM hb_dbgActivateBreakArray( HB_DEBUGINFO * info );
  172. static PHB_ITEM hb_dbgActivateModuleArray( void );
  173. static PHB_ITEM hb_dbgActivateVarArray( int nVars, HB_VARINFO * aVars );
  174. static void hb_dbgAddLocal( HB_DEBUGINFO * info, const char * szName, int nIndex, int nFrame );
  175. static void hb_dbgAddModule( const char * szName );
  176. static void hb_dbgAddStack( HB_DEBUGINFO * info, const char * szName, int nProcLevel );
  177. static void hb_dbgAddStatic( HB_DEBUGINFO * info, const char * szName, int nIndex, PHB_ITEM pFrame );
  178. static void hb_dbgAddVar( int * nVars, HB_VARINFO ** aVars, const char * szName, char cType, int nIndex, int nFrame, PHB_ITEM pFrame );
  179. static void hb_dbgAddStopLines( PHB_ITEM pItem );
  180. static void hb_dbgEndProc( HB_DEBUGINFO * info );
  181. static PHB_ITEM hb_dbgEval( HB_DEBUGINFO * info, HB_WATCHPOINT * watch );
  182. static PHB_ITEM hb_dbgEvalMacro( const char * szExpr, PHB_ITEM pItem );
  183. static PHB_ITEM hb_dbgEvalMakeBlock( HB_WATCHPOINT * watch );
  184. static PHB_ITEM hb_dbgEvalResolve( HB_DEBUGINFO * info, HB_WATCHPOINT * watch );
  185. static HB_BOOL hb_dbgIsAltD( void );
  186. static HB_BOOL hb_dbgIsBreakPoint( HB_DEBUGINFO * info, const char * szModule, int nLine );
  187. static HB_BOOL hb_dbgEqual( PHB_ITEM pItem1, PHB_ITEM pItem2 );
  188. static void hb_dbgQuit( HB_DEBUGINFO * info );
  189. static void hb_dbgRelease( void );
  190. static PHB_ITEM hb_dbgVarGet( HB_VARINFO * scope );
  191. static void hb_dbgVarSet( HB_VARINFO * scope, PHB_ITEM xNewValue );
  192. static void hb_dbgActivate( HB_DEBUGINFO * info )
  193. {
  194. PHB_DYNS pDynSym = hb_dynsymFind( "__DBGENTRY" );
  195. if( pDynSym && hb_dynsymIsFunction( pDynSym ) )
  196. {
  197. int i;
  198. PHB_ITEM aCallStack = hb_itemArrayNew( info->nCallStackLen );
  199. PHB_ITEM aModules;
  200. PHB_ITEM aBreak;
  201. for( i = 0; i < info->nCallStackLen; i++ )
  202. {
  203. HB_CALLSTACKINFO * pEntry = &info->aCallStack[ i ];
  204. PHB_ITEM aEntry = hb_itemArrayNew( 6 );
  205. PHB_ITEM pItem;
  206. hb_arraySetC( aEntry, 1, pEntry->szModule );
  207. hb_arraySetC( aEntry, 2, pEntry->szFunction );
  208. hb_arraySetNL( aEntry, 3, pEntry->nLine );
  209. hb_arraySetNL( aEntry, 4, pEntry->nProcLevel );
  210. pItem = hb_dbgActivateVarArray( pEntry->nLocals, pEntry->aLocals );
  211. hb_arraySet( aEntry, 5, pItem );
  212. hb_itemRelease( pItem );
  213. pItem = hb_dbgActivateVarArray( pEntry->nStatics, pEntry->aStatics );
  214. hb_arraySet( aEntry, 6, pItem );
  215. hb_itemRelease( pItem );
  216. hb_arraySet( aCallStack, info->nCallStackLen - i, aEntry );
  217. hb_itemRelease( aEntry );
  218. }
  219. aModules = hb_dbgActivateModuleArray();
  220. aBreak = hb_dbgActivateBreakArray( info );
  221. hb_vmPushDynSym( pDynSym );
  222. hb_vmPushNil();
  223. hb_vmPushLong( HB_DBG_ACTIVATE );
  224. hb_vmPushPointer( info );
  225. hb_vmPushLong( info->nProcLevel );
  226. hb_vmPush( aCallStack );
  227. hb_vmPush( aModules );
  228. hb_vmPush( aBreak );
  229. hb_itemRelease( aCallStack );
  230. hb_itemRelease( aModules );
  231. hb_itemRelease( aBreak );
  232. hb_vmDo( 6 );
  233. }
  234. }
  235. static PHB_ITEM hb_dbgActivateBreakArray( HB_DEBUGINFO * info )
  236. {
  237. int i;
  238. PHB_ITEM pArray = hb_itemArrayNew( info->nBreakPoints );
  239. for( i = 0; i < info->nBreakPoints; i++ )
  240. {
  241. PHB_ITEM pBreak = hb_itemArrayNew( 3 );
  242. if( !info->aBreak[ i ].szFunction )
  243. {
  244. hb_arraySetNI( pBreak, 1, info->aBreak[ i ].nLine );
  245. hb_arraySetC( pBreak, 2, info->aBreak[ i ].szModule );
  246. }
  247. else
  248. hb_arraySetC( pBreak, 3, info->aBreak[ i ].szFunction );
  249. hb_arraySet( pArray, i + 1, pBreak );
  250. hb_itemRelease( pBreak );
  251. }
  252. return pArray;
  253. }
  254. static PHB_ITEM hb_dbgActivateModuleArray( void )
  255. {
  256. PHB_ITEM pArray;
  257. int i;
  258. HB_DBGCOMMON_LOCK
  259. pArray = hb_itemArrayNew( s_common.nModules );
  260. for( i = 0; i < s_common.nModules; i++ )
  261. {
  262. PHB_ITEM pModule = hb_itemArrayNew( 4 );
  263. PHB_ITEM item;
  264. hb_arraySetC( pModule, 1, s_common.aModules[ i ].szModule );
  265. item = hb_dbgActivateVarArray( s_common.aModules[ i ].nStatics,
  266. s_common.aModules[ i ].aStatics );
  267. hb_arraySet( pModule, 2, item );
  268. hb_itemRelease( item );
  269. item = hb_dbgActivateVarArray( s_common.aModules[ i ].nGlobals,
  270. s_common.aModules[ i ].aGlobals );
  271. hb_arraySet( pModule, 3, item );
  272. hb_itemRelease( item );
  273. item = hb_dbgActivateVarArray( s_common.aModules[ i ].nExternGlobals,
  274. s_common.aModules[ i ].aExternGlobals );
  275. hb_arraySet( pModule, 4, item );
  276. hb_itemRelease( item );
  277. hb_arraySet( pArray, i + 1, pModule );
  278. hb_itemRelease( pModule );
  279. }
  280. HB_DBGCOMMON_UNLOCK
  281. return pArray;
  282. }
  283. static PHB_ITEM hb_dbgActivateVarArray( int nVars, HB_VARINFO * aVars )
  284. {
  285. int i;
  286. PHB_ITEM pArray = hb_itemArrayNew( nVars );
  287. for( i = 0; i < nVars; i++ )
  288. {
  289. PHB_ITEM aVar = hb_itemArrayNew( 4 );
  290. hb_arraySetC( aVar, 1, aVars[ i ].szName );
  291. hb_arraySetNL( aVar, 2, aVars[ i ].nIndex );
  292. hb_arraySetCL( aVar, 3, &aVars[ i ].cType, 1 );
  293. if( aVars[ i ].cType == 'S' )
  294. hb_arraySet( aVar, 4, aVars[ i ].frame.ptr );
  295. else
  296. hb_arraySetNL( aVar, 4, aVars[ i ].frame.num );
  297. hb_arraySet( pArray, i + 1, aVar );
  298. hb_itemRelease( aVar );
  299. }
  300. return pArray;
  301. }
  302. void hb_dbgEntry( int nMode, int nLine, const char * szName, int nIndex, PHB_ITEM pFrame )
  303. {
  304. int i;
  305. HB_ULONG nProcLevel;
  306. char szProcName[ HB_SYMBOL_NAME_LEN + HB_SYMBOL_NAME_LEN + 5 ];
  307. HB_DEBUGINFO ** infoPtr = ( HB_DEBUGINFO ** ) hb_stackDebugInfo();
  308. HB_DEBUGINFO * info = *infoPtr;
  309. if( info == HB_DBGINFO_DISABLE )
  310. return;
  311. else if( nMode != HB_DBG_VMQUIT )
  312. {
  313. if( !info )
  314. {
  315. info = *infoPtr = ( HB_DEBUGINFO * ) hb_xgrab( sizeof( HB_DEBUGINFO ) );
  316. memset( info, 0, sizeof( HB_DEBUGINFO ) );
  317. info->bCBTrace = HB_TRUE;
  318. }
  319. else if( info->bInside || info->bQuit )
  320. return;
  321. }
  322. switch( nMode )
  323. {
  324. case HB_DBG_MODULENAME:
  325. HB_TRACE( HB_TR_DEBUG, ( "MODULENAME %s", szName ) );
  326. if( szName[ strlen( szName ) - 1 ] == ':' )
  327. return;
  328. hb_procinfo( 0, szProcName, NULL, NULL );
  329. if( !strncmp( szProcName, "(_INITSTATICS", 13 ) )
  330. info->bInitStatics = HB_TRUE;
  331. else if( !strncmp( szProcName, "(_INITGLOBALS", 13 ) )
  332. info->bInitGlobals = HB_TRUE;
  333. else if( !strncmp( szProcName, "(_INITLINES", 11 ) )
  334. info->bInitLines = HB_TRUE;
  335. if( info->bInitStatics || info->bInitGlobals )
  336. hb_dbgAddModule( szName );
  337. else if( !strncmp( szProcName, "(b)", 3 ) )
  338. info->bCodeBlock = HB_TRUE;
  339. else if( info->bNextRoutine )
  340. info->bNextRoutine = HB_FALSE;
  341. hb_dbgAddStack( info, szName, hb_dbg_ProcLevel() );
  342. for( i = 0; i < info->nBreakPoints; i++ )
  343. {
  344. if( info->aBreak[ i ].szFunction
  345. && !strcmp( info->aBreak[ i ].szFunction, szProcName ) )
  346. {
  347. hb_dbg_InvokeDebug( HB_TRUE );
  348. break;
  349. }
  350. }
  351. return;
  352. case HB_DBG_LOCALNAME:
  353. HB_TRACE( HB_TR_DEBUG, ( "LOCALNAME %s index %d", szName, nIndex ) );
  354. hb_dbgAddLocal( info, szName, nIndex, hb_dbg_ProcLevel() );
  355. return;
  356. case HB_DBG_STATICNAME:
  357. HB_TRACE( HB_TR_DEBUG, ( "STATICNAME %s index %d frame %p", szName, nIndex, pFrame ) );
  358. hb_dbgAddStatic( info, szName, nIndex, pFrame );
  359. return;
  360. case HB_DBG_SHOWLINE:
  361. {
  362. HB_CALLSTACKINFO * pTop = &info->aCallStack[ info->nCallStackLen - 1 ];
  363. HB_BOOL bOldClsScope;
  364. HB_TRACE( HB_TR_DEBUG, ( "SHOWLINE %d", nLine ) );
  365. nProcLevel = hb_dbg_ProcLevel();
  366. /* Check if we've hit a tracepoint */
  367. bOldClsScope = hb_clsSetScope( HB_FALSE );
  368. for( i = 0; i < info->nTracePoints; i++ )
  369. {
  370. HB_TRACEPOINT * tp = &info->aTrace[ i ];
  371. PHB_ITEM xValue;
  372. xValue = hb_dbgEval( info, &info->aWatch[ tp->nIndex ] );
  373. if( !xValue )
  374. xValue = hb_itemNew( NULL );
  375. if( HB_ITEM_TYPE( xValue ) != HB_ITEM_TYPE( tp->xValue ) ||
  376. !hb_dbgEqual( xValue, tp->xValue ) )
  377. {
  378. hb_itemCopy( tp->xValue, xValue );
  379. hb_itemRelease( xValue );
  380. pTop->nLine = nLine;
  381. info->nProcLevel = nProcLevel - ( hb_dbgIsAltD() ? 2 : 0 );
  382. info->bTraceOver = HB_FALSE;
  383. info->bCodeBlock = HB_FALSE;
  384. info->bGo = HB_FALSE;
  385. if( info->bToCursor )
  386. {
  387. info->bToCursor = HB_FALSE;
  388. hb_xfree( info->szToCursorModule );
  389. }
  390. info->bNextRoutine = HB_FALSE;
  391. hb_dbgActivate( info );
  392. return;
  393. }
  394. hb_itemRelease( xValue );
  395. }
  396. hb_clsSetScope( bOldClsScope );
  397. if( hb_dbgIsBreakPoint( info, pTop->szModule, nLine )
  398. || hb_dbg_InvokeDebug( HB_FALSE )
  399. || ( info->pFunInvoke && info->pFunInvoke() ) )
  400. {
  401. info->bTraceOver = HB_FALSE;
  402. if( info->bToCursor )
  403. {
  404. info->bToCursor = HB_FALSE;
  405. hb_xfree( info->szToCursorModule );
  406. }
  407. info->bNextRoutine = HB_FALSE;
  408. info->bGo = HB_FALSE;
  409. }
  410. /* Check if we must skip every level above info->nTraceLevel */
  411. if( info->bTraceOver )
  412. {
  413. if( info->nTraceLevel < info->nCallStackLen )
  414. return;
  415. info->bTraceOver = HB_FALSE;
  416. }
  417. /* Check if we're skipping to a specific line of source */
  418. if( info->bToCursor )
  419. {
  420. if( nLine == info->nToCursorLine
  421. && FILENAME_EQUAL( pTop->szModule, info->szToCursorModule ) )
  422. {
  423. hb_xfree( info->szToCursorModule );
  424. info->bToCursor = HB_FALSE;
  425. }
  426. else
  427. return;
  428. }
  429. /* Check if'we skipping to the end of current routine */
  430. if( info->bNextRoutine )
  431. return;
  432. if( info->bCodeBlock )
  433. {
  434. info->bCodeBlock = HB_FALSE;
  435. if( !info->bCBTrace )
  436. return;
  437. }
  438. pTop->nLine = nLine;
  439. if( !info->bGo )
  440. {
  441. info->nProcLevel = nProcLevel - ( hb_dbgIsAltD() ? 2 : 0 );
  442. hb_dbgActivate( info );
  443. }
  444. return;
  445. }
  446. case HB_DBG_ENDPROC:
  447. if( info->bQuit )
  448. return;
  449. HB_TRACE( HB_TR_DEBUG, ( "ENDPROC %d", nLine ) );
  450. if( info->bInitLines )
  451. hb_dbgAddStopLines( hb_stackReturnItem() );
  452. info->bCodeBlock = HB_FALSE;
  453. info->bInitStatics = HB_FALSE;
  454. info->bInitGlobals = HB_FALSE;
  455. info->bInitLines = HB_FALSE;
  456. hb_dbgEndProc( info );
  457. return;
  458. case HB_DBG_VMQUIT:
  459. if( info )
  460. {
  461. hb_dbgQuit( info );
  462. hb_xfree( info );
  463. *infoPtr = HB_DBGINFO_DISABLE;
  464. }
  465. if( nIndex != 0 )
  466. {
  467. /* main thread exit and HVM cleanup, release common module info */
  468. hb_dbgRelease();
  469. }
  470. return;
  471. }
  472. }
  473. static const char * hb_dbgStripModuleName( const char * szName )
  474. {
  475. const char * ptr;
  476. if( ( ptr = strrchr( szName, '/' ) ) != NULL )
  477. szName = ptr + 1;
  478. if( ( ptr = strrchr( szName, '\\' ) ) != NULL )
  479. szName = ptr + 1;
  480. return szName;
  481. }
  482. void hb_dbgAddBreak( void * handle, const char * szModule, int nLine, const char * szFunction )
  483. {
  484. HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle;
  485. HB_BREAKPOINT * pBreak;
  486. pBreak = ARRAY_ADD( HB_BREAKPOINT, info->aBreak, info->nBreakPoints );
  487. pBreak->szModule = hb_strdup( szModule );
  488. pBreak->nLine = nLine;
  489. if( szFunction )
  490. pBreak->szFunction = hb_strdup( szFunction );
  491. else
  492. pBreak->szFunction = NULL;
  493. }
  494. static void hb_dbgAddLocal( HB_DEBUGINFO * info, const char * szName, int nIndex, int nFrame )
  495. {
  496. if( info->bInitGlobals )
  497. {
  498. HB_MODULEINFO * module;
  499. HB_DBGCOMMON_LOCK
  500. module = &s_common.aModules[ s_common.nModules - 1 ];
  501. hb_dbgAddVar( &module->nGlobals, &module->aGlobals, szName,
  502. 'G', nIndex, hb_dbg_vmVarGCount(), NULL );
  503. HB_DBGCOMMON_UNLOCK
  504. }
  505. else
  506. {
  507. HB_CALLSTACKINFO * top = &info->aCallStack[ info->nCallStackLen - 1 ];
  508. hb_dbgAddVar( &top->nLocals, &top->aLocals, szName, 'L', nIndex, nFrame, NULL );
  509. }
  510. }
  511. static void hb_dbgAddModule( const char * szName )
  512. {
  513. char * szModuleName;
  514. const char * szFuncName;
  515. int iLen;
  516. szName = hb_dbgStripModuleName( szName );
  517. szFuncName = strrchr( szName, ':' );
  518. iLen = szFuncName ? ( int ) ( szFuncName - szName ) : ( int ) strlen( szName );
  519. szModuleName = hb_strndup( szName, iLen );
  520. HB_DBGCOMMON_LOCK
  521. if( !s_common.nModules || strcmp( s_common.aModules[ s_common.nModules - 1 ].szModule, szModuleName ) )
  522. {
  523. HB_MODULEINFO * pModule;
  524. pModule = ARRAY_ADD( HB_MODULEINFO, s_common.aModules, s_common.nModules );
  525. pModule->szModule = szModuleName;
  526. pModule->nStatics = 0;
  527. pModule->nGlobals = 0;
  528. pModule->nExternGlobals = 0;
  529. szModuleName = NULL;
  530. }
  531. HB_DBGCOMMON_UNLOCK
  532. if( szModuleName )
  533. hb_xfree( szModuleName );
  534. }
  535. static void hb_dbgAddStack( HB_DEBUGINFO * info, const char * szName, int nProcLevel )
  536. {
  537. char szBuff[ HB_SYMBOL_NAME_LEN + HB_SYMBOL_NAME_LEN + 5 ];
  538. HB_CALLSTACKINFO * top;
  539. const char * szFunction = strrchr( szName, ':' );
  540. if( szFunction )
  541. szFunction++;
  542. top = ARRAY_ADD( HB_CALLSTACKINFO, info->aCallStack, info->nCallStackLen );
  543. if( info->bCodeBlock )
  544. {
  545. memcpy( szBuff, "(b)", 3 );
  546. hb_strncpy( szBuff + 3, szFunction, sizeof( szBuff ) - 4 );
  547. top->szFunction = hb_strdup( szBuff );
  548. }
  549. else
  550. {
  551. if( szFunction )
  552. {
  553. top->szFunction = hb_strdup( szFunction );
  554. }
  555. else
  556. {
  557. /* We're in an (_INITSTATICSnnnnn) pseudo-function */
  558. hb_procinfo( 0, szBuff, NULL, NULL );
  559. top->szFunction = hb_strdup( szBuff );
  560. }
  561. }
  562. szName = hb_dbgStripModuleName( szName );
  563. if( szFunction )
  564. top->szModule = hb_strndup( szName, szFunction - szName - 1 );
  565. else
  566. top->szModule = hb_strdup( szName );
  567. top->nProcLevel = nProcLevel;
  568. top->nLine = 0;
  569. top->nLocals = 0;
  570. top->nStatics = 0;
  571. }
  572. static void hb_dbgAddStatic( HB_DEBUGINFO * info, const char * szName, int nIndex, PHB_ITEM pFrame )
  573. {
  574. if( info->bInitGlobals )
  575. {
  576. HB_MODULEINFO * module;
  577. HB_DBGCOMMON_LOCK
  578. module = &s_common.aModules[ s_common.nModules - 1 ];
  579. hb_dbgAddVar( &module->nExternGlobals, &module->aExternGlobals, szName,
  580. 'G', nIndex, hb_dbg_vmVarGCount(), NULL );
  581. HB_DBGCOMMON_UNLOCK
  582. }
  583. else if( info->bInitStatics )
  584. {
  585. HB_MODULEINFO * module;
  586. HB_DBGCOMMON_LOCK
  587. module = &s_common.aModules[ s_common.nModules - 1 ];
  588. hb_dbgAddVar( &module->nStatics, &module->aStatics, szName,
  589. 'S', nIndex, 0, pFrame );
  590. HB_DBGCOMMON_UNLOCK
  591. }
  592. else
  593. {
  594. HB_CALLSTACKINFO * top = &info->aCallStack[ info->nCallStackLen - 1 ];
  595. hb_dbgAddVar( &top->nStatics, &top->aStatics, szName, 'S', nIndex, 0, pFrame );
  596. }
  597. }
  598. static void hb_dbgAddStopLines( PHB_ITEM pItem )
  599. {
  600. HB_ISIZ i, nLinesLen;
  601. HB_DBGCOMMON_LOCK
  602. if( !s_common.pStopLines )
  603. {
  604. s_common.pStopLines = hb_itemNew( pItem );
  605. }
  606. else
  607. {
  608. HB_ISIZ j;
  609. HB_ISIZ nItemLen = hb_itemSize( pItem );
  610. nLinesLen = hb_itemSize( s_common.pStopLines );
  611. for( i = 1; i <= nItemLen; i++ )
  612. {
  613. PHB_ITEM pEntry = hb_arrayGetItemPtr( pItem, i );
  614. const char * szModule = hb_arrayGetCPtr( pEntry, 1 );
  615. HB_BOOL bFound = HB_FALSE;
  616. szModule = hb_dbgStripModuleName( szModule );
  617. for( j = 1; j <= nLinesLen; j++ )
  618. {
  619. PHB_ITEM pLines = hb_arrayGetItemPtr( s_common.pStopLines, j );
  620. if( !strcmp( hb_arrayGetCPtr( pLines, 1 ), szModule ) )
  621. {
  622. /* Merge stopline info */
  623. HB_ISIZ nOrigMin = hb_arrayGetNS( pLines, 2 );
  624. HB_ISIZ nNewMin = hb_arrayGetNS( pEntry, 2 );
  625. HB_ISIZ nOrigLen = hb_arrayGetCLen( pLines, 3 );
  626. HB_ISIZ nNewLen = hb_arrayGetCLen( pEntry, 3 );
  627. HB_ISIZ nMin = HB_MIN( nNewMin, nOrigMin );
  628. HB_ISIZ nMax = HB_MAX( nNewMin + ( nNewLen << 3 ) - 1,
  629. nOrigMin + ( nOrigLen << 3 ) - 1 );
  630. const char * pOrigBuffer = hb_arrayGetCPtr( pLines, 3 );
  631. const char * pNewBuffer = hb_arrayGetCPtr( pEntry, 3 );
  632. HB_ISIZ nLen = ( ( nMax - nMin ) >> 3 ) + 1;
  633. HB_ISIZ k;
  634. char * pBuffer = ( char * ) hb_xgrab( nLen + 1 );
  635. hb_xmemset( pBuffer, 0, nLen );
  636. /* the bitfields with line numbers should use
  637. * 8bit alignment so it's safe to use byte copy
  638. */
  639. memmove( &pBuffer[ ( nNewMin - nMin ) >> 3 ], pNewBuffer, nNewLen );
  640. nOrigMin = ( nOrigMin - nMin ) >> 3;
  641. for( k = 0; k < nOrigLen; k++ )
  642. pBuffer[ nOrigMin + k ] |= pOrigBuffer[ k ];
  643. hb_arraySetNS( pLines, 2, nMin );
  644. if( !hb_arraySetCLPtr( pLines, 3, pBuffer, nLen ) )
  645. hb_xfree( pBuffer );
  646. bFound = HB_TRUE;
  647. break;
  648. }
  649. }
  650. if( !bFound )
  651. hb_arrayAddForward( s_common.pStopLines, pEntry );
  652. }
  653. }
  654. nLinesLen = hb_itemSize( s_common.pStopLines );
  655. for( i = 1; i <= nLinesLen; i++ )
  656. {
  657. PHB_ITEM pEntry = hb_arrayGetItemPtr( s_common.pStopLines, i );
  658. const char * szModule = hb_arrayGetCPtr( pEntry, 1 );
  659. if( szModule )
  660. {
  661. const char * szName = hb_dbgStripModuleName( szModule );
  662. if( szName != szModule )
  663. hb_arraySetCLPtr( pEntry, 1, hb_strdup( szName ), strlen( szName ) );
  664. }
  665. }
  666. HB_DBGCOMMON_UNLOCK
  667. }
  668. static void hb_dbgAddVar( int * nVars, HB_VARINFO ** aVars, const char * szName, char cType, int nIndex, int nFrame, PHB_ITEM pFrame )
  669. {
  670. HB_VARINFO * var;
  671. var = ARRAY_ADD( HB_VARINFO, *aVars, *nVars );
  672. /* TODO/TOFIX: value should be duplicated here and then released */
  673. var->szName = ( char * ) szName;
  674. var->cType = cType;
  675. var->nIndex = nIndex;
  676. if( cType == 'S' )
  677. var->frame.ptr = pFrame;
  678. else
  679. var->frame.num = nFrame;
  680. }
  681. void hb_dbgAddWatch( void * handle, const char * szExpr, HB_BOOL bTrace )
  682. {
  683. HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle;
  684. HB_WATCHPOINT * pWatch;
  685. pWatch = ARRAY_ADD( HB_WATCHPOINT, info->aWatch, info->nWatchPoints );
  686. pWatch->szExpr = hb_strdup( szExpr );
  687. pWatch->pBlock = NULL;
  688. pWatch->nVars = 0;
  689. if( bTrace )
  690. {
  691. HB_TRACEPOINT * pTrace = ARRAY_ADD( HB_TRACEPOINT, info->aTrace, info->nTracePoints );
  692. pTrace->nIndex = info->nWatchPoints - 1;
  693. pTrace->xValue = hb_dbgEval( info, pWatch );
  694. }
  695. }
  696. static void hb_dbgClearWatch( HB_WATCHPOINT * pWatch )
  697. {
  698. hb_xfree( pWatch->szExpr );
  699. if( pWatch->pBlock )
  700. hb_itemRelease( pWatch->pBlock );
  701. if( pWatch->nVars )
  702. {
  703. int i;
  704. for( i = 0; i < pWatch->nVars; i++ )
  705. hb_xfree( pWatch->aVars[ i ] );
  706. hb_xfree( pWatch->aVars );
  707. }
  708. }
  709. void hb_dbgDelBreak( void * handle, int nBreak )
  710. {
  711. HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle;
  712. HB_BREAKPOINT * pBreak = &info->aBreak[ nBreak ];
  713. hb_xfree( pBreak->szModule );
  714. if( pBreak->szFunction )
  715. hb_xfree( pBreak->szFunction );
  716. ARRAY_DEL( HB_BREAKPOINT, info->aBreak, info->nBreakPoints, nBreak );
  717. }
  718. void hb_dbgDelWatch( void * handle, int nWatch )
  719. {
  720. HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle;
  721. HB_WATCHPOINT * pWatch = &info->aWatch[ nWatch ];
  722. int i;
  723. hb_dbgClearWatch( pWatch );
  724. ARRAY_DEL( HB_WATCHPOINT, info->aWatch, info->nWatchPoints, nWatch );
  725. for( i = 0; i < info->nTracePoints; i++ )
  726. {
  727. HB_TRACEPOINT * pTrace = &info->aTrace[ i ];
  728. if( pTrace->nIndex == nWatch )
  729. {
  730. if( pTrace->xValue )
  731. hb_itemRelease( pTrace->xValue );
  732. ARRAY_DEL( HB_TRACEPOINT, info->aTrace, info->nTracePoints, i );
  733. i--;
  734. }
  735. else if( pTrace->nIndex > nWatch )
  736. pTrace->nIndex--;
  737. }
  738. }
  739. static void hb_dbgEndProc( HB_DEBUGINFO * info )
  740. {
  741. HB_CALLSTACKINFO * top;
  742. if( !info->nCallStackLen )
  743. return;
  744. top = &info->aCallStack[ --info->nCallStackLen ];
  745. hb_xfree( top->szFunction );
  746. hb_xfree( top->szModule );
  747. if( top->nLocals )
  748. hb_xfree( top->aLocals );
  749. if( top->nStatics )
  750. hb_xfree( top->aStatics );
  751. if( !info->nCallStackLen )
  752. {
  753. hb_xfree( info->aCallStack );
  754. info->aCallStack = NULL;
  755. }
  756. }
  757. static HB_BOOL hb_dbgEqual( PHB_ITEM pItem1, PHB_ITEM pItem2 )
  758. {
  759. if( HB_ITEM_TYPE( pItem1 ) != HB_ITEM_TYPE( pItem2 ) )
  760. return HB_FALSE;
  761. if( HB_IS_NIL( pItem1 ) )
  762. return HB_IS_NIL( pItem2 );
  763. if( HB_IS_LOGICAL( pItem1 ) )
  764. return ( hb_itemGetL( pItem1 ) == hb_itemGetL( pItem2 ) );
  765. if( HB_IS_POINTER( pItem1 ) )
  766. return ( hb_itemGetPtr( pItem1 ) == hb_itemGetPtr( pItem2 ) );
  767. if( HB_IS_STRING( pItem1 ) )
  768. return !hb_itemStrCmp( pItem1, pItem2, HB_TRUE );
  769. if( HB_IS_NUMINT( pItem1 ) )
  770. return ( hb_itemGetNInt( pItem1 ) == hb_itemGetNInt( pItem2 ) );
  771. if( HB_IS_NUMERIC( pItem1 ) )
  772. return ( hb_itemGetND( pItem1 ) == hb_itemGetND( pItem2 ) );
  773. if( HB_IS_ARRAY( pItem1 ) )
  774. return ( hb_arrayId( pItem1 ) == hb_arrayId( pItem2 ) );
  775. if( HB_IS_HASH( pItem1 ) )
  776. return ( hb_hashId( pItem1 ) == hb_hashId( pItem2 ) );
  777. return HB_FALSE;
  778. }
  779. static PHB_ITEM hb_dbgEval( HB_DEBUGINFO * info, HB_WATCHPOINT * watch )
  780. {
  781. PHB_ITEM xResult = NULL;
  782. HB_TRACE( HB_TR_DEBUG, ( "expr %s", watch->szExpr ) );
  783. /* Check if we have a cached pBlock */
  784. if( !watch->pBlock )
  785. watch->pBlock = hb_dbgEvalMakeBlock( watch );
  786. if( watch->pBlock )
  787. {
  788. PHB_ITEM aVars = hb_dbgEvalResolve( info, watch );
  789. PHB_ITEM aNewVars = hb_itemArrayNew( watch->nVars );
  790. int i;
  791. hb_arrayCopy( aVars, aNewVars, NULL, NULL, NULL );
  792. info->bInside = HB_TRUE;
  793. xResult = hb_itemDo( watch->pBlock, 1, aNewVars );
  794. info->bInside = HB_FALSE;
  795. for( i = 0; i < watch->nVars; i++ )
  796. {
  797. PHB_ITEM xOldValue = hb_itemArrayGet( aVars, i + 1 );
  798. PHB_ITEM xNewValue = hb_itemArrayGet( aNewVars, i + 1 );
  799. if( !hb_dbgEqual( xOldValue, xNewValue ) )
  800. hb_dbgVarSet( &watch->aScopes[ i ], xNewValue );
  801. hb_itemRelease( xOldValue );
  802. hb_itemRelease( xNewValue );
  803. }
  804. hb_itemRelease( aVars );
  805. hb_itemRelease( aNewVars );
  806. for( i = 0; i < watch->nVars; i++ )
  807. {
  808. if( watch->aScopes[ i ].cType == 'M' )
  809. hb_xfree( watch->aScopes[ i ].szName );
  810. }
  811. if( watch->nVars )
  812. hb_xfree( watch->aScopes );
  813. }
  814. return xResult;
  815. }
  816. static PHB_ITEM hb_dbgEvalMacro( const char * szExpr, PHB_ITEM pItem )
  817. {
  818. PHB_ITEM pStr;
  819. const char * type;
  820. pStr = hb_itemPutC( NULL, szExpr );
  821. type = hb_macroGetType( pStr );
  822. hb_itemRelease( pStr );
  823. if( ( !strcmp( type, "U" ) || !strcmp( type, "UE" ) ) )
  824. return NULL;
  825. hb_vmPushString( szExpr, strlen( szExpr ) );
  826. hb_macroGetValue( hb_stackItemFromTop( -1 ), 0, HB_SM_RT_MACRO );
  827. hb_itemMove( pItem, hb_stackItemFromTop( -1 ) );
  828. hb_stackPop();
  829. return pItem;
  830. }
  831. #define IS_IDENT_START( c ) HB_ISFIRSTIDCHAR( ( HB_UCHAR ) ( c ) )
  832. #define IS_IDENT_CHAR( c ) HB_ISNEXTIDCHAR( ( HB_UCHAR ) ( c ) )
  833. static int hb_dbgEvalSubstituteVar( HB_WATCHPOINT * watch, char * szWord, int nStart, int nLen )
  834. {
  835. int j;
  836. char * t;
  837. for( j = 0; j < watch->nVars; j++ )
  838. {
  839. if( !strcmp( szWord, watch->aVars[ j ] ) )
  840. break;
  841. }
  842. if( j == watch->nVars )
  843. *ARRAY_ADD( char *, watch->aVars, watch->nVars ) = szWord;
  844. else
  845. hb_xfree( szWord );
  846. t = ( char * ) hb_xgrab( strlen( watch->szExpr ) - nLen + 9 + 1 );
  847. memmove( t, watch->szExpr, nStart );
  848. memmove( t + nStart, "__dbg[", 6 );
  849. t[ nStart + 6 ] = '0' + ( char ) ( ( j + 1 ) / 10 );
  850. t[ nStart + 7 ] = '0' + ( char ) ( ( j + 1 ) % 10 );
  851. t[ nStart + 8 ] = ']';
  852. hb_strncpy( t + nStart + 9, watch->szExpr + nStart + nLen, strlen( watch->szExpr ) - nLen - nStart );
  853. hb_xfree( watch->szExpr );
  854. watch->szExpr = t;
  855. return nStart + 9;
  856. }
  857. static PHB_ITEM hb_dbgEvalMakeBlock( HB_WATCHPOINT * watch )
  858. {
  859. int i = 0;
  860. PHB_ITEM pBlock;
  861. HB_BOOL bAfterId = HB_FALSE;
  862. char * s;
  863. HB_ISIZ buffsize;
  864. watch->nVars = 0;
  865. while( watch->szExpr[ i ] )
  866. {
  867. char c = watch->szExpr[ i ];
  868. if( IS_IDENT_START( c ) )
  869. {
  870. int nStart = i, nLen;
  871. int j = i;
  872. char * szWord;
  873. while( c && IS_IDENT_CHAR( c ) )
  874. {
  875. j++;
  876. c = watch->szExpr[ j ];
  877. }
  878. nLen = j - i;
  879. szWord = hb_strndup( watch->szExpr + i, nLen );
  880. i = j;
  881. if( c )
  882. {
  883. while( watch->szExpr[ i ] && watch->szExpr[ i ] == ' ' )
  884. i++;
  885. if( watch->szExpr[ i ] == '(' )
  886. {
  887. hb_xfree( szWord );
  888. continue;
  889. }
  890. if( watch->szExpr[ i ] == '-' && watch->szExpr[ i + 1 ] == '>' )
  891. {
  892. i += 2;
  893. while( ( c = watch->szExpr[ i ] ) != '\0' && IS_IDENT_CHAR( c ) )
  894. i++;
  895. hb_xfree( szWord );
  896. continue;
  897. }
  898. }
  899. hb_strupr( szWord );
  900. i = hb_dbgEvalSubstituteVar( watch, szWord, nStart, nLen );
  901. bAfterId = HB_TRUE;
  902. continue;
  903. }
  904. if( c == '.' )
  905. {
  906. if( watch->szExpr[ i + 1 ]
  907. && strchr( "TtFf", watch->szExpr[ i + 1 ] )
  908. && watch->szExpr[ i + 2 ] == '.' )
  909. {
  910. i += 3;
  911. }
  912. else if( !hb_strnicmp( watch->szExpr + i + 1, "OR.", 3 ) )
  913. {
  914. i += 4;
  915. }
  916. else if( !hb_strnicmp( watch->szExpr + i + 1, "AND.", 4 )
  917. || !hb_strnicmp( watch->szExpr + i + 1, "NOT.", 4 ) )
  918. {
  919. i += 5;
  920. }
  921. else
  922. {
  923. i++;
  924. }
  925. bAfterId = HB_FALSE;
  926. continue;
  927. }
  928. if( c == ':'
  929. || ( c == '-' && watch->szExpr[ i + 1 ] == '>'
  930. && IS_IDENT_START( watch->szExpr[ i + 2 ] ) ) )
  931. {
  932. if( c == ':' && watch->szExpr[ i + 1 ] == ':' )
  933. {
  934. i = hb_dbgEvalSubstituteVar( watch, hb_strdup( "SELF" ), i, 1 );
  935. bAfterId = HB_TRUE;
  936. continue;
  937. }
  938. if( c == '-' )
  939. i++;
  940. i++;
  941. while( watch->szExpr[ i ] && IS_IDENT_CHAR( watch->szExpr[ i ] ) )
  942. i++;
  943. bAfterId = HB_TRUE;
  944. continue;
  945. }
  946. if( strchr( " !#$=<>(+-*/%^|,{&", c ) )
  947. {
  948. i++;
  949. bAfterId = HB_FALSE;
  950. continue;
  951. }
  952. if( c == '\'' || c == '\"' )
  953. {
  954. i++;
  955. while( watch->szExpr[ i ] && watch->szExpr[ i ] != c )
  956. i++;
  957. if( watch->szExpr[ i ] )
  958. i++;
  959. bAfterId = HB_TRUE;
  960. continue;
  961. }
  962. if( c == '[' )
  963. {
  964. i++;
  965. if( bAfterId )
  966. bAfterId = HB_FALSE;
  967. else
  968. {
  969. while( watch->szExpr[ i ] && watch->szExpr[ i ] != ']' )
  970. i++;
  971. if( watch->szExpr[ i ] )
  972. i++;
  973. bAfterId = HB_TRUE;
  974. }
  975. continue;
  976. }
  977. i++;
  978. }
  979. buffsize = 8 + strlen( watch->szExpr ) + 1;
  980. s = ( char * ) hb_xgrab( buffsize + 1 );
  981. hb_strncpy( s, "{|__dbg|", buffsize );
  982. hb_strncat( s, watch->szExpr, buffsize );
  983. hb_strncat( s, "}", buffsize );
  984. pBlock = hb_itemNew( NULL );
  985. if( ! hb_dbgEvalMacro( s, pBlock ) )
  986. {
  987. hb_itemRelease( pBlock );
  988. pBlock = NULL;
  989. }
  990. hb_xfree( s );
  991. return pBlock;
  992. }
  993. static PHB_ITEM hb_dbgEvalResolve( HB_DEBUGINFO * info, HB_WATCHPOINT * watch )
  994. {
  995. int i;
  996. HB_CALLSTACKINFO * top = &info->aCallStack[ info->nCallStackLen - 1 ];
  997. PHB_ITEM aVars = hb_itemArrayNew( watch->nVars );
  998. HB_VARINFO * scopes;
  999. HB_MODULEINFO * module = NULL;
  1000. int nProcLevel;
  1001. if( !watch->nVars )
  1002. return aVars;
  1003. scopes = ( HB_VARINFO * ) hb_xgrab( watch->nVars * sizeof( HB_VARINFO ) );
  1004. nProcLevel = hb_dbg_ProcLevel();
  1005. HB_DBGCOMMON_LOCK
  1006. for( i = 0; i < s_common.nModules; i++ )
  1007. {
  1008. if( !strcmp( s_common.aModules[ i ].szModule, top->szModule ) )
  1009. {
  1010. module = &s_common.aModules[ i ];
  1011. break;
  1012. }
  1013. }
  1014. for( i = 0; i < watch->nVars; i++ )
  1015. {
  1016. char * name = watch->aVars[ i ];
  1017. HB_VARINFO * var;
  1018. int j;
  1019. PHB_ITEM pItem;
  1020. for( j = 0; j < top->nLocals; j++ )
  1021. {
  1022. var = &top->aLocals[ j ];
  1023. if( !strcmp( name, var->szName ) )
  1024. {
  1025. scopes[ i ].cType = 'L';
  1026. scopes[ i ].frame.num = nProcLevel - var->frame.num;
  1027. scopes[ i ].nIndex = var->nIndex;
  1028. hb_itemArrayPut( aVars, i + 1, hb_dbgVarGet( &scopes[ i ] ) );
  1029. break;
  1030. }
  1031. }
  1032. if( j < top->nLocals )
  1033. continue;
  1034. for( j = 0; j < top->nStatics; j++ )
  1035. {
  1036. var = &top->aStatics[ j ];
  1037. if( !strcmp( name, var->szName ) )
  1038. {
  1039. scopes[ i ].cType = 'S';
  1040. scopes[ i ].frame.ptr = var->frame.ptr;
  1041. scopes[ i ].nIndex = var->nIndex;
  1042. hb_itemArrayPut( aVars, i + 1, hb_dbgVarGet( &scopes[ i ] ) );
  1043. break;
  1044. }
  1045. }
  1046. if( j < top->nStatics )
  1047. continue;
  1048. if( module )
  1049. {
  1050. for( j = 0; j < module->nStatics; j++ )
  1051. {
  1052. var = &module->aStatics[ j ];
  1053. if( !strcmp( name, var->szName ) )
  1054. {
  1055. scopes[ i ].cType = 'S';
  1056. scopes[ i ].frame.ptr = var->frame.ptr;
  1057. scopes[ i ].nIndex = var->nIndex;
  1058. hb_itemArrayPut( aVars, i + 1, hb_dbgVarGet( &scopes[ i ] ) );
  1059. break;
  1060. }
  1061. }
  1062. if( j < module->nStatics )
  1063. continue;
  1064. for( j = 0; j < module->nGlobals; j++ )
  1065. {
  1066. var = &module->aGlobals[ j ];
  1067. if( !strcmp( name, var->szName ) )
  1068. {
  1069. scopes[ i ].cType = 'G';
  1070. scopes[ i ].frame.num = var->frame.num;
  1071. scopes[ i ].nIndex = var->nIndex;
  1072. hb_itemArrayPut( aVars, i + 1, hb_dbgVarGet( &scopes[ i ] ) );
  1073. break;
  1074. }
  1075. }
  1076. if( j < module->nGlobals )
  1077. continue;
  1078. for( j = 0; j < module->nExternGlobals; j++ )
  1079. {
  1080. var = &module->aExternGlobals[ j ];
  1081. if( !strcmp( name, var->szName ) )
  1082. {
  1083. scopes[ i ].cType = 'G';
  1084. scopes[ i ].frame.num = var->frame.num;
  1085. scopes[ i ].nIndex = var->nIndex;
  1086. hb_itemArrayPut( aVars, i + 1, hb_dbgVarGet( &scopes[ i ] ) );
  1087. break;
  1088. }
  1089. }
  1090. if( j < module->nExternGlobals )
  1091. continue;
  1092. }
  1093. scopes[ i ].cType = 'M';
  1094. scopes[ i ].szName = hb_strdup( name );
  1095. pItem = hb_dbgVarGet( &scopes[ i ] );
  1096. if( pItem )
  1097. hb_itemArrayPut( aVars, i + 1, pItem );
  1098. if( scopes[ i ].cType == 'F' )
  1099. hb_itemRelease( pItem );
  1100. }
  1101. watch->aScopes = scopes;
  1102. HB_DBGCOMMON_UNLOCK
  1103. return aVars;
  1104. }
  1105. PHB_ITEM hb_dbgGetExpressionValue( void * handle, const char *expression )
  1106. {
  1107. HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle;
  1108. PHB_ITEM result;
  1109. HB_WATCHPOINT point;
  1110. point.szExpr = hb_strdup( expression );
  1111. point.pBlock = NULL;
  1112. point.nVars = 0;
  1113. result = hb_dbgEval( info, &point );
  1114. hb_dbgClearWatch( &point );
  1115. return result;
  1116. }
  1117. PHB_ITEM hb_dbgGetSourceFiles( void * handle )
  1118. {
  1119. PHB_ITEM ret;
  1120. HB_ISIZ nModules;
  1121. HB_ISIZ i;
  1122. /* HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle; */
  1123. HB_SYMBOL_UNUSED( handle );
  1124. HB_DBGCOMMON_LOCK
  1125. nModules = hb_itemSize( s_common.pStopLines );
  1126. ret = hb_itemArrayNew( nModules );
  1127. for( i = 1; i <= nModules; i++ )
  1128. hb_arraySet( ret, i, hb_arrayGetItemPtr( hb_arrayGetItemPtr( s_common.pStopLines, i ), 1 ) );
  1129. HB_DBGCOMMON_UNLOCK
  1130. return ret;
  1131. }
  1132. PHB_ITEM hb_dbgGetWatchValue( void * handle, int nWatch )
  1133. {
  1134. HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle;
  1135. return hb_dbgEval( info, &( info->aWatch[ nWatch ] ) );
  1136. }
  1137. static HB_BOOL hb_dbgIsAltD( void )
  1138. {
  1139. char szName[ HB_SYMBOL_NAME_LEN + HB_SYMBOL_NAME_LEN + 5];
  1140. hb_procinfo( 1, szName, NULL, NULL );
  1141. return !strcmp( szName, "ALTD" );
  1142. }
  1143. static HB_BOOL hb_dbgIsBreakPoint( HB_DEBUGINFO * info, const char * szModule, int nLine )
  1144. {
  1145. int i;
  1146. for( i = 0; i < info->nBreakPoints; i++ )
  1147. {
  1148. HB_BREAKPOINT * point = &info->aBreak[ i ];
  1149. if( point->nLine == nLine
  1150. && FILENAME_EQUAL( szModule, point->szModule ) )
  1151. return HB_TRUE;
  1152. }
  1153. return HB_FALSE;
  1154. }
  1155. HB_BOOL hb_dbgIsValidStopLine( void * handle, const char * szModule, int nLine )
  1156. {
  1157. HB_BOOL fResult = HB_FALSE;
  1158. HB_ISIZ nModules;
  1159. HB_ISIZ i;
  1160. /* HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle; */
  1161. HB_SYMBOL_UNUSED( handle );
  1162. HB_DBGCOMMON_LOCK
  1163. nModules = hb_itemSize( s_common.pStopLines );
  1164. for( i = 1; i <= nModules; i++ )
  1165. {
  1166. PHB_ITEM pEntry = hb_arrayGetItemPtr( s_common.pStopLines, i );
  1167. if( FILENAME_EQUAL( hb_arrayGetCPtr( pEntry, 1 ), szModule ) )
  1168. {
  1169. int nMin = hb_arrayGetNL( pEntry, 2 );
  1170. int nOfs = nLine - nMin;
  1171. if( nOfs >= 0 && ( HB_SIZE ) ( nOfs >> 3 ) < hb_arrayGetCLen( pEntry, 3 ) )
  1172. fResult = ( hb_arrayGetCPtr( pEntry, 3 )[ nOfs >> 3 ] & ( 1 << ( nOfs & 0x07 ) ) ) != 0;
  1173. break;
  1174. }
  1175. }
  1176. HB_DBGCOMMON_UNLOCK
  1177. return fResult;
  1178. }
  1179. static void hb_dbgQuit( HB_DEBUGINFO * info )
  1180. {
  1181. while( info->nWatchPoints )
  1182. {
  1183. hb_dbgDelWatch( info, info->nWatchPoints - 1 );
  1184. }
  1185. while( info->nBreakPoints )
  1186. {
  1187. hb_dbgDelBreak( info, info->nBreakPoints - 1 );
  1188. }
  1189. while( info->nCallStackLen )
  1190. {
  1191. hb_dbgEndProc( info );
  1192. }
  1193. if( info->bToCursor )
  1194. {
  1195. info->bToCursor = HB_FALSE;
  1196. hb_xfree( info->szToCursorModule );
  1197. }
  1198. }
  1199. static void hb_dbgRelease( void )
  1200. {
  1201. if( s_common.pStopLines )
  1202. {
  1203. hb_itemRelease( s_common.pStopLines );
  1204. s_common.pStopLines = NULL;
  1205. }
  1206. while( s_common.nModules )
  1207. {
  1208. int nModules = s_common.nModules - 1;
  1209. HB_MODULEINFO *module = &s_common.aModules[ nModules ];
  1210. if( module->nStatics )
  1211. {
  1212. hb_xfree( module->aStatics );
  1213. }
  1214. if( module->nGlobals )
  1215. {
  1216. hb_xfree( module->aGlobals );
  1217. }
  1218. if( module->nExternGlobals )
  1219. {
  1220. hb_xfree( module->aExternGlobals );
  1221. }
  1222. if( module->szModule )
  1223. {
  1224. hb_xfree( module->szModule );
  1225. }
  1226. ARRAY_DEL( HB_MODULEINFO, s_common.aModules, s_common.nModules, nModules );
  1227. }
  1228. }
  1229. void hb_dbgSetCBTrace( void * handle, HB_BOOL bCBTrace )
  1230. {
  1231. HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle;
  1232. info->bCBTrace = bCBTrace;
  1233. }
  1234. void hb_dbgSetGo( void * handle )
  1235. {
  1236. HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle;
  1237. info->bGo = HB_TRUE;
  1238. }
  1239. void hb_dbgSetInvoke( void * handle, HB_BOOL ( *pFunInvoke )( void ) )
  1240. {
  1241. HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle;
  1242. info->pFunInvoke = pFunInvoke;
  1243. }
  1244. void hb_dbgSetNextRoutine( void * handle )
  1245. {
  1246. HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle;
  1247. info->bNextRoutine = HB_TRUE;
  1248. }
  1249. void hb_dbgSetQuit( void * handle )
  1250. {
  1251. HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle;
  1252. info->bQuit = HB_TRUE;
  1253. }
  1254. void hb_dbgSetToCursor( void * handle, const char * szModule, int nLine )
  1255. {
  1256. HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle;
  1257. info->bToCursor = HB_TRUE;
  1258. info->szToCursorModule = hb_strdup( szModule );
  1259. info->nToCursorLine = nLine;
  1260. }
  1261. void hb_dbgSetTrace( void * handle )
  1262. {
  1263. HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle;
  1264. info->bTraceOver = HB_TRUE;
  1265. info->nTraceLevel = info->nCallStackLen;
  1266. }
  1267. void hb_dbgSetWatch( void * handle, int nWatch, const char * szExpr, HB_BOOL bTrace )
  1268. {
  1269. HB_DEBUGINFO * info = ( HB_DEBUGINFO * ) handle;
  1270. HB_WATCHPOINT * pWatch = &info->aWatch[ nWatch ];
  1271. int i;
  1272. hb_dbgClearWatch( pWatch );
  1273. pWatch->szExpr = hb_strdup( szExpr );
  1274. pWatch->pBlock = NULL;
  1275. for( i = 0; i < info->nTracePoints; i++ )
  1276. {
  1277. HB_TRACEPOINT * pTrace = &info->aTrace[ i ];
  1278. if( pTrace->nIndex == nWatch )
  1279. {
  1280. if( pTrace->xValue )
  1281. hb_itemRelease( pTrace->xValue );
  1282. ARRAY_DEL( HB_TRACEPOINT, info->aTrace, info->nTracePoints, i );
  1283. break;
  1284. }
  1285. }
  1286. if( bTrace )
  1287. {
  1288. HB_TRACEPOINT * pTrace = ARRAY_ADD( HB_TRACEPOINT, info->aTrace, info->nTracePoints );
  1289. pTrace->nIndex = nWatch;
  1290. pTrace->xValue = hb_dbgEval( info, pWatch );
  1291. }
  1292. }
  1293. static PHB_ITEM hb_dbgVarGet( HB_VARINFO * scope )
  1294. {
  1295. switch( scope->cType )
  1296. {
  1297. case 'G':
  1298. return hb_dbg_vmVarGGet( scope->frame.num, scope->nIndex );
  1299. case 'L':
  1300. return hb_dbg_vmVarLGet( scope->frame.num, scope->nIndex );
  1301. case 'S':
  1302. return hb_dbg_vmVarSGet( scope->frame.ptr, scope->nIndex );
  1303. case 'M':
  1304. {
  1305. PHB_DYNS pDyn;
  1306. pDyn = hb_dynsymFind( scope->szName );
  1307. if( pDyn != NULL )
  1308. {
  1309. PHB_ITEM pItem = hb_memvarGetValueBySym( pDyn );
  1310. if( !pItem )
  1311. {
  1312. pItem = hb_itemNew( NULL );
  1313. if( hb_rddFieldGet( pItem, hb_dynsymSymbol( pDyn ) ) == HB_SUCCESS )
  1314. {
  1315. scope->cType = 'F';
  1316. }
  1317. else
  1318. {
  1319. hb_itemRelease( pItem );
  1320. pItem = NULL;
  1321. }
  1322. }
  1323. return pItem;
  1324. }
  1325. }
  1326. }
  1327. return NULL;
  1328. }
  1329. static void hb_dbgVarSet( HB_VARINFO * scope, PHB_ITEM xNewValue )
  1330. {
  1331. switch( scope->cType )
  1332. {
  1333. case 'G':
  1334. case 'L':
  1335. case 'S':
  1336. hb_itemCopy( hb_dbgVarGet( scope ), xNewValue );
  1337. break;
  1338. case 'M':
  1339. {
  1340. PHB_DYNS pDynSym = hb_dynsymFind( "__MVPUT" );
  1341. if( pDynSym && hb_dynsymIsFunction( pDynSym ) )
  1342. {
  1343. hb_vmPushDynSym( pDynSym );
  1344. hb_vmPushNil();
  1345. hb_vmPushString( scope->szName, strlen( scope->szName ) );
  1346. hb_vmPush( xNewValue );
  1347. hb_vmDo( 2 );
  1348. }
  1349. break;
  1350. }
  1351. }
  1352. }
  1353. /*
  1354. * .prg functions
  1355. */
  1356. HB_FUNC( __DBGSETENTRY )
  1357. {
  1358. hb_dbg_SetEntry( hb_dbgEntry );
  1359. }
  1360. HB_FUNC( __DBGSETGO )
  1361. {
  1362. void * ptr = hb_parptr( 1 );
  1363. if( ptr )
  1364. hb_dbgSetGo( ptr );
  1365. }
  1366. HB_FUNC( __DBGSETTRACE )
  1367. {
  1368. void * ptr = hb_parptr( 1 );
  1369. if( ptr )
  1370. hb_dbgSetTrace( ptr );
  1371. }
  1372. HB_FUNC( __DBGSETCBTRACE )
  1373. {
  1374. void * ptr = hb_parptr( 1 );
  1375. if( ptr )
  1376. hb_dbgSetCBTrace( ptr, hb_parl( 2 ) );
  1377. }
  1378. HB_FUNC( __DBGSETNEXTROUTINE )
  1379. {
  1380. void * ptr = hb_parptr( 1 );
  1381. if( ptr )
  1382. hb_dbgSetNextRoutine( ptr );
  1383. }
  1384. HB_FUNC( __DBGSETQUIT )
  1385. {
  1386. void * ptr = hb_parptr( 1 );
  1387. if( ptr )
  1388. hb_dbgSetQuit( ptr );
  1389. }
  1390. HB_FUNC( __DBGSETTOCURSOR )
  1391. {
  1392. void * ptr = hb_parptr( 1 );
  1393. if( ptr )
  1394. hb_dbgSetToCursor( ptr, hb_parc( 2 ), hb_parni( 3 ) );
  1395. }
  1396. HB_FUNC( __DBGGETEXPRVALUE )
  1397. {
  1398. void * ptr = hb_parptr( 1 );
  1399. if( ptr )
  1400. {
  1401. PHB_ITEM pItem;
  1402. if( HB_ISCHAR( 2 ) )
  1403. pItem = hb_dbgGetExpressionValue( hb_parptr( 1 ), hb_parc( 2 ) );
  1404. else
  1405. pItem = hb_dbgGetWatchValue( hb_parptr( 1 ), hb_parni( 2 ) - 1 );
  1406. if( pItem )
  1407. {
  1408. hb_storl( HB_TRUE, 3 );
  1409. hb_itemReturnRelease( pItem );
  1410. }
  1411. else
  1412. hb_storl( HB_FALSE, 3 );
  1413. }
  1414. }
  1415. HB_FUNC( __DBGGETSOURCEFILES )
  1416. {
  1417. void * ptr = hb_parptr( 1 );
  1418. if( ptr )
  1419. hb_itemReturnRelease( hb_dbgGetSourceFiles( ptr ) );
  1420. }
  1421. HB_FUNC( __DBGISVALIDSTOPLINE )
  1422. {
  1423. void * ptr = hb_parptr( 1 );
  1424. if( ptr )
  1425. hb_retl( hb_dbgIsValidStopLine( ptr, hb_parc( 2 ), hb_parni( 3 ) ) );
  1426. }
  1427. HB_FUNC( __DBGADDBREAK )
  1428. {
  1429. void * ptr = hb_parptr( 1 );
  1430. if( ptr )
  1431. hb_dbgAddBreak( ptr, hb_parc( 2 ), hb_parni( 3 ), NULL );
  1432. }
  1433. HB_FUNC( __DBGDELBREAK )
  1434. {
  1435. void * ptr = hb_parptr( 1 );
  1436. if( ptr )
  1437. hb_dbgDelBreak( ptr, hb_parni( 2 ) );
  1438. }
  1439. HB_FUNC( __DBGADDWATCH )
  1440. {
  1441. void * ptr = hb_parptr( 1 );
  1442. if( ptr )
  1443. hb_dbgAddWatch( ptr, hb_parc( 2 ), hb_parl( 3 ) );
  1444. }
  1445. HB_FUNC( __DBGDELWATCH )
  1446. {
  1447. void * ptr = hb_parptr( 1 );
  1448. if( ptr )
  1449. hb_dbgDelWatch( ptr, hb_parni( 2 ) );
  1450. }
  1451. HB_FUNC( __DBGSETWATCH )
  1452. {
  1453. void * ptr = hb_parptr( 1 );
  1454. if( ptr )
  1455. hb_dbgSetWatch( ptr, hb_parni( 2 ), hb_parc( 3 ), hb_parl( 4 ) );
  1456. }
  1457. HB_FUNC( __DBGSENDMSG )
  1458. {
  1459. hb_dbg_objSendMessage( hb_parnl( 1 ), hb_param( 2, HB_IT_ANY ),
  1460. hb_param( 3, HB_IT_ANY ), 4 );
  1461. }