@@ -207,48 +207,111 @@ PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, long line_num TSRML
207
207
{
208
208
php_stream_statbuf ssb ;
209
209
char realpath [MAXPATHLEN ];
210
+ const char * original_path = path ;
211
+ zend_bool pending ;
210
212
211
- if (php_stream_stat_path (path , & ssb ) != FAILURE ) {
212
- if (ssb .sb .st_mode & (S_IFREG |S_IFLNK )) {
213
- HashTable * broken ;
214
- phpdbg_breakfile_t new_break ;
215
- size_t path_len = 0L ;
213
+ HashTable * broken , * file_breaks = & PHPDBG_G (bp )[PHPDBG_BREAK_FILE ];
214
+ phpdbg_breakfile_t new_break ;
215
+ size_t path_len = 0L ;
216
216
217
- if (VCWD_REALPATH (path , realpath )) {
218
- path = realpath ;
217
+ if (VCWD_REALPATH (path , realpath )) {
218
+ path = realpath ;
219
+ }
220
+ path_len = strlen (path );
221
+
222
+ if (!zend_hash_str_exists (& PHPDBG_G (file_sources ), path , path_len )) {
223
+ if (php_stream_stat_path (path , & ssb ) == FAILURE ) {
224
+ if (original_path [0 ] == '/' ) {
225
+ phpdbg_error ("breakpoint" , "type=\"nofile\" add=\"fail\" file=\"%s\"" , "Cannot stat %s, it does not exist" , original_path );
226
+ return ;
219
227
}
228
+
229
+ file_breaks = & PHPDBG_G (bp )[PHPDBG_BREAK_FILE_PENDING ];
230
+ path = original_path ;
220
231
path_len = strlen (path );
232
+ pending = 1 ;
233
+ } else if (!(ssb .sb .st_mode & (S_IFREG |S_IFLNK ))) {
234
+ phpdbg_error ("breakpoint" , "type=\"notregular\" add=\"fail\" file=\"%s\"" , "Cannot set breakpoint in %s, it is not a regular file" , path );
235
+ return ;
236
+ }
237
+ }
221
238
222
- if (!(broken = zend_hash_str_find_ptr (& PHPDBG_G (bp )[PHPDBG_BREAK_FILE ], path , path_len ))) {
223
- HashTable breaks ;
239
+ if (!(broken = zend_hash_str_find_ptr (file_breaks , path , path_len ))) {
240
+ HashTable breaks ;
241
+ zend_hash_init (& breaks , 8 , NULL , phpdbg_file_breaks_dtor , 0 );
224
242
225
- zend_hash_init (& breaks , 8 , NULL , phpdbg_file_breaks_dtor , 0 );
243
+ broken = zend_hash_str_add_mem (file_breaks , path , path_len , & breaks , sizeof (HashTable ));
244
+ }
226
245
227
- broken = zend_hash_str_update_mem (& PHPDBG_G (bp )[PHPDBG_BREAK_FILE ], path , path_len , & breaks , sizeof (HashTable ));
228
- }
246
+ if (!zend_hash_index_exists (broken , line_num )) {
247
+ PHPDBG_BREAK_INIT (new_break , PHPDBG_BREAK_FILE );
248
+ new_break .filename = estrndup (path , path_len );
249
+ new_break .line = line_num ;
250
+
251
+ zend_hash_index_update_mem (broken , line_num , & new_break , sizeof (phpdbg_breakfile_t ));
229
252
230
- if (! zend_hash_index_exists ( broken , line_num ) ) {
231
- PHPDBG_G (flags ) |= PHPDBG_HAS_FILE_BP ;
253
+ if (pending ) {
254
+ PHPDBG_G (flags ) |= PHPDBG_HAS_PENDING_FILE_BP ;
232
255
233
- PHPDBG_BREAK_INIT ( new_break , PHPDBG_BREAK_FILE );
234
- new_break . filename = estrndup ( path , path_len );
235
- new_break . line = line_num ;
256
+ phpdbg_notice ( "breakpoint" , "add=\"success\" id=\"%d\" file=\"%s\" line=\"%ld\" pending=\"pending\"" , "Pending breakpoint #%d added at %s:%ld" , new_break . id , new_break . filename , new_break . line );
257
+ } else {
258
+ PHPDBG_G ( flags ) |= PHPDBG_HAS_FILE_BP ;
236
259
237
- zend_hash_index_update_mem (broken , line_num , & new_break , sizeof (phpdbg_breakfile_t ));
260
+ phpdbg_notice ("breakpoint" , "add=\"success\" id=\"%d\" file=\"%s\" line=\"%ld\"" , "Breakpoint #%d added at %s:%ld" , new_break .id , new_break .filename , new_break .line );
261
+ }
238
262
239
- phpdbg_notice ("breakpoint" , "add=\"success\" id=\"%d\" file=\"%s\" line=\"%ld\"" , "Breakpoint #%d added at %s:%ld" , new_break .id , new_break .filename , new_break .line );
263
+ PHPDBG_BREAK_MAPPING (new_break .id , broken );
264
+ } else {
265
+ phpdbg_error ("breakpoint" , "type=\"exists\" add=\"fail\" file=\"%s\" line=\"%ld\"" , "Breakpoint at %s:%ld exists" , path , line_num );
266
+ }
267
+ } /* }}} */
240
268
241
- PHPDBG_BREAK_MAPPING (new_break .id , broken );
242
- } else {
243
- phpdbg_error ("breakpoint" , "type=\"exists\" add=\"fail\" file=\"%s\" line=\"%ld\"" , "Breakpoint at %s:%ld exists" , path , line_num );
269
+ PHPDBG_API void phpdbg_resolve_pending_file_break (const char * file TSRMLS_DC ) /* {{{ */
270
+ {
271
+ HashTable * fileht ;
272
+ uint filelen = strlen (file );
273
+ zend_string * cur ;
274
+
275
+ ZEND_HASH_FOREACH_STR_KEY_PTR (& PHPDBG_G (bp )[PHPDBG_BREAK_FILE_PENDING ], cur , fileht ) {
276
+ if (cur -> len < filelen && file [filelen - cur -> len - 1 ] == '/' && !memcmp (file + filelen - cur -> len , cur -> val , cur -> len )) {
277
+ phpdbg_breakfile_t * brake , new_brake ;
278
+ HashTable * master ;
279
+ dtor_func_t dtor ;
280
+
281
+ PHPDBG_G (flags ) |= PHPDBG_HAS_FILE_BP ;
282
+
283
+ if (!(master = zend_hash_str_find_ptr (& PHPDBG_G (bp )[PHPDBG_BREAK_FILE ], file , filelen ))) {
284
+ dtor = PHPDBG_G (bp )[PHPDBG_BREAK_FILE_PENDING ].pDestructor ;
285
+ PHPDBG_G (bp )[PHPDBG_BREAK_FILE_PENDING ].pDestructor = NULL ;
286
+ fileht = zend_hash_str_add_mem (& PHPDBG_G (bp )[PHPDBG_BREAK_FILE ], file , filelen , fileht , sizeof (HashTable ));
244
287
}
245
288
246
- } else {
247
- phpdbg_error ("breakpoint" , "type=\"notregular\" add=\"fail\" file=\"%s\"" , "Cannot set breakpoint in %s, it is not a regular file" , path );
289
+ ZEND_HASH_FOREACH_PTR (fileht , brake ) {
290
+ new_brake = * brake ;
291
+ new_brake .filename = estrndup (file , filelen );
292
+ PHPDBG_BREAK_UNMAPPING (brake -> id );
293
+
294
+ if (master ) {
295
+ zend_hash_index_update_mem (master , brake -> line , & new_brake , sizeof (phpdbg_breakfile_t ));
296
+ PHPDBG_BREAK_MAPPING (brake -> id , master );
297
+ } else {
298
+ efree ((char * ) brake -> filename );
299
+ * brake = new_brake ;
300
+ PHPDBG_BREAK_MAPPING (brake -> id , fileht );
301
+ }
302
+ } ZEND_HASH_FOREACH_END ();
303
+
304
+ zend_hash_del (& PHPDBG_G (bp )[PHPDBG_BREAK_FILE_PENDING ], cur );
305
+
306
+ if (!master ) {
307
+ PHPDBG_G (bp )[PHPDBG_BREAK_FILE_PENDING ].pDestructor = dtor ;
308
+ }
309
+
310
+ if (!zend_hash_num_elements (& PHPDBG_G (bp )[PHPDBG_BREAK_FILE_PENDING ])) {
311
+ PHPDBG_G (flags ) &= ~PHPDBG_HAS_PENDING_FILE_BP ;
312
+ }
248
313
}
249
- } else {
250
- phpdbg_error ("breakpoint" , "type=\"nofile\" add=\"fail\" file=\"%s\"" , "Cannot stat %s, it does not exist" , path );
251
- }
314
+ } ZEND_HASH_FOREACH_END ();
252
315
} /* }}} */
253
316
254
317
PHPDBG_API void phpdbg_set_breakpoint_symbol (const char * name , size_t name_len TSRMLS_DC ) /* {{{ */
@@ -1048,6 +1111,7 @@ PHPDBG_API void phpdbg_delete_breakpoint(zend_ulong num TSRMLS_DC) /* {{{ */
1048
1111
PHPDBG_API void phpdbg_clear_breakpoints (TSRMLS_D ) /* {{{ */
1049
1112
{
1050
1113
zend_hash_clean (& PHPDBG_G (bp )[PHPDBG_BREAK_FILE ]);
1114
+ zend_hash_clean (& PHPDBG_G (bp )[PHPDBG_BREAK_FILE_PENDING ]);
1051
1115
zend_hash_clean (& PHPDBG_G (bp )[PHPDBG_BREAK_SYM ]);
1052
1116
zend_hash_clean (& PHPDBG_G (bp )[PHPDBG_BREAK_OPLINE ]);
1053
1117
zend_hash_clean (& PHPDBG_G (bp )[PHPDBG_BREAK_METHOD_OPLINE ]);
@@ -1283,7 +1347,20 @@ PHPDBG_API void phpdbg_print_breakpoints(zend_ulong type TSRMLS_DC) /* {{{ */
1283
1347
((phpdbg_breakbase_t * ) brake )-> disabled ? " [disabled]" : "" );
1284
1348
} ZEND_HASH_FOREACH_END ();
1285
1349
} ZEND_HASH_FOREACH_END ();
1350
+ } if ((PHPDBG_G (flags ) & PHPDBG_HAS_PENDING_FILE_BP )) {
1351
+ HashTable * points ;
1352
+
1353
+ phpdbg_out (SEPARATE "\n" );
1354
+ phpdbg_out ("Pending File Breakpoints:\n" );
1355
+ ZEND_HASH_FOREACH_PTR (& PHPDBG_G (bp )[PHPDBG_BREAK_FILE_PENDING ], points ) {
1356
+ phpdbg_breakfile_t * brake ;
1286
1357
1358
+ ZEND_HASH_FOREACH_PTR (points , brake ) {
1359
+ phpdbg_writeln ("file" , "id=\"%d\" name=\"%s\" line=\"%lu\" disabled=\"%s\" pending=\"pending\"" , "#%d\t\t%s:%lu%s" ,
1360
+ brake -> id , brake -> filename , brake -> line ,
1361
+ ((phpdbg_breakbase_t * ) brake )-> disabled ? " [disabled]" : "" );
1362
+ } ZEND_HASH_FOREACH_END ();
1363
+ } ZEND_HASH_FOREACH_END ();
1287
1364
} break ;
1288
1365
1289
1366
case PHPDBG_BREAK_OPLINE : if ((PHPDBG_G (flags ) & PHPDBG_HAS_OPLINE_BP )) {
0 commit comments