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

/tags/harbour-1.0.1/source/debug/dbgentry.c

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