| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
|
|
2
|
|
|
|
|
|
|
package DB ; |
|
3
|
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
## |
|
5
|
|
|
|
|
|
|
## Expedient fix for perl 5.8.0. True DB::DB is further down. |
|
6
|
|
|
|
|
|
|
## |
|
7
|
|
|
|
|
|
|
## |
|
8
|
0
|
|
|
0
|
0
|
|
sub DB {} |
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
|
|
12
|
1
|
|
|
1
|
|
2941
|
use Tk ; |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
# |
|
15
|
|
|
|
|
|
|
# If you've loaded this file via a browser |
|
16
|
|
|
|
|
|
|
# select "Save As..." from your file menu |
|
17
|
|
|
|
|
|
|
# |
|
18
|
|
|
|
|
|
|
# ptkdb Perl Tk perl Debugger |
|
19
|
|
|
|
|
|
|
# |
|
20
|
|
|
|
|
|
|
# Copyright 1998, 2003, Andrew E. Page |
|
21
|
|
|
|
|
|
|
# All rights reserved. |
|
22
|
|
|
|
|
|
|
# |
|
23
|
|
|
|
|
|
|
# This program is free software; you can redistribute it and/or modify |
|
24
|
|
|
|
|
|
|
# it under the terms of either: |
|
25
|
|
|
|
|
|
|
# |
|
26
|
|
|
|
|
|
|
# a) the GNU General Public License as published by the Free |
|
27
|
|
|
|
|
|
|
# Software Foundation; either version 1, or (at your option) any |
|
28
|
|
|
|
|
|
|
# later version, or |
|
29
|
|
|
|
|
|
|
# |
|
30
|
|
|
|
|
|
|
# b) the "Artistic License" which comes with this Kit. |
|
31
|
|
|
|
|
|
|
# |
|
32
|
|
|
|
|
|
|
# This program is distributed in the hope that it will be useful, |
|
33
|
|
|
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
34
|
|
|
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either |
|
35
|
|
|
|
|
|
|
# the GNU General Public License or the Artistic License for more details. |
|
36
|
|
|
|
|
|
|
# |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
#################################### |
|
40
|
|
|
|
|
|
|
### Sample .Xresources for ptkdb ### |
|
41
|
|
|
|
|
|
|
#################################### |
|
42
|
|
|
|
|
|
|
# /* |
|
43
|
|
|
|
|
|
|
# * Perl Tk Debugger XResources. |
|
44
|
|
|
|
|
|
|
# * Note... These resources are subject to change. |
|
45
|
|
|
|
|
|
|
# * |
|
46
|
|
|
|
|
|
|
# * Use 'xfontsel' to select different fonts. |
|
47
|
|
|
|
|
|
|
# * |
|
48
|
|
|
|
|
|
|
# * Append these resource to ~/.Xdefaults | ~/.Xresources |
|
49
|
|
|
|
|
|
|
# * and use xrdb -override ~/.Xdefaults | ~/.Xresources |
|
50
|
|
|
|
|
|
|
# * to activate them. |
|
51
|
|
|
|
|
|
|
# */ |
|
52
|
|
|
|
|
|
|
# /* Set Value to se to place scrollbars on the right side of windows |
|
53
|
|
|
|
|
|
|
# CAUTION: extra whitespace at the end of the line is causing |
|
54
|
|
|
|
|
|
|
# failures with Tk800.011. |
|
55
|
|
|
|
|
|
|
# */ |
|
56
|
|
|
|
|
|
|
# ptkdb*scrollbars: sw |
|
57
|
|
|
|
|
|
|
# |
|
58
|
|
|
|
|
|
|
# /* controls where the code pane is oriented, down the left side, or across the top */ |
|
59
|
|
|
|
|
|
|
# /* values can be set to left, right, top, bottom */ |
|
60
|
|
|
|
|
|
|
# ptkdb*codeside: left |
|
61
|
|
|
|
|
|
|
# /* |
|
62
|
|
|
|
|
|
|
# * Background color for the balloon |
|
63
|
|
|
|
|
|
|
# * CAUTION: For certain versions of Tk trailing |
|
64
|
|
|
|
|
|
|
# * characters after the color produces an error |
|
65
|
|
|
|
|
|
|
# */ |
|
66
|
|
|
|
|
|
|
# ptkdb.frame2.frame1.rotext.balloon.background: green |
|
67
|
|
|
|
|
|
|
# ptkdb.frame2.frame1.rotext.balloon.font: fixed /* Hot Variable Balloon Font */ |
|
68
|
|
|
|
|
|
|
# |
|
69
|
|
|
|
|
|
|
# |
|
70
|
|
|
|
|
|
|
# ptkdb.frame*font: fixed /* Menu Bar */ |
|
71
|
|
|
|
|
|
|
# ptkdb.frame.menubutton.font: fixed /* File menu */ |
|
72
|
|
|
|
|
|
|
# ptkdb.frame2.frame1.rotext.font: fixed /* Code Pane */ |
|
73
|
|
|
|
|
|
|
# ptkdb.notebook.datapage.frame1.hlist.font: fixed /* Expression Notebook Page */ |
|
74
|
|
|
|
|
|
|
# |
|
75
|
|
|
|
|
|
|
# ptkdb.notebook.subspage*font: fixed /* Subroutine Notebook Page */ |
|
76
|
|
|
|
|
|
|
# ptkdb.notebook.brkptspage*entry.font: fixed /* Delete Breakpoint Buttons */ |
|
77
|
|
|
|
|
|
|
# ptkdb.notebook.brkptspage*button.font: fixed /* Breakpoint Expression Entries */ |
|
78
|
|
|
|
|
|
|
# ptkdb.notebook.brkptspage*button1.font: fixed /* Breakpoint Expression Entries */ |
|
79
|
|
|
|
|
|
|
# ptkdb.notebook.brkptspage*checkbutton.font: fixed /* Breakpoint Checkbuttons */ |
|
80
|
|
|
|
|
|
|
# ptkdb.notebook.brkptspage*label.font: fixed /* Breakpoint "Cond" label */ |
|
81
|
|
|
|
|
|
|
# |
|
82
|
|
|
|
|
|
|
# ptkdb.toplevel.frame.textundo.font: fixed /* Eval Expression Entry Window */ |
|
83
|
|
|
|
|
|
|
# ptkdb.toplevel.frame1.text.font: fixed /* Eval Expression Results Window */ |
|
84
|
|
|
|
|
|
|
# ptkdb.toplevel.button.font: fixed /* "Eval..." Button */ |
|
85
|
|
|
|
|
|
|
# ptkdb.toplevel.button1.font: fixed /* "Clear Eval" Button */ |
|
86
|
|
|
|
|
|
|
# ptkdb.toplevel.button2.font: fixed /* "Clear Results" Button */ |
|
87
|
|
|
|
|
|
|
# ptkdb.toplevel.button3.font: fixed /* "Clear Dismiss" Button */ |
|
88
|
|
|
|
|
|
|
# |
|
89
|
|
|
|
|
|
|
# |
|
90
|
|
|
|
|
|
|
# /* |
|
91
|
|
|
|
|
|
|
# * Background color for where the debugger has stopped |
|
92
|
|
|
|
|
|
|
# */ |
|
93
|
|
|
|
|
|
|
# ptkdb*stopcolor: blue |
|
94
|
|
|
|
|
|
|
# |
|
95
|
|
|
|
|
|
|
# /* |
|
96
|
|
|
|
|
|
|
# * Background color for set breakpoints |
|
97
|
|
|
|
|
|
|
# */ |
|
98
|
|
|
|
|
|
|
# ptkdb*breaktagcolor: red |
|
99
|
|
|
|
|
|
|
# |
|
100
|
|
|
|
|
|
|
# /* |
|
101
|
|
|
|
|
|
|
# * Font for where the debugger has stopped |
|
102
|
|
|
|
|
|
|
# */ |
|
103
|
|
|
|
|
|
|
# ptkdb*stopfont: -*-fixed-bold-*-*-*-*-*-*-*-*-*-*-* |
|
104
|
|
|
|
|
|
|
# |
|
105
|
|
|
|
|
|
|
# /* |
|
106
|
|
|
|
|
|
|
# * Background color for the search tag |
|
107
|
|
|
|
|
|
|
# */ |
|
108
|
|
|
|
|
|
|
# ptkdb*searchtagcolor: green |
|
109
|
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
use strict ; |
|
111
|
|
|
|
|
|
|
use vars qw($VERSION @dbline %dbline); |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
# |
|
115
|
|
|
|
|
|
|
# This package is the main_window object |
|
116
|
|
|
|
|
|
|
# for the debugger. We start with the Devel:: |
|
117
|
|
|
|
|
|
|
# prefix because we want to install it with |
|
118
|
|
|
|
|
|
|
# the DB:: package that is required to be in a Devel/ |
|
119
|
|
|
|
|
|
|
# subdir of a directory in the @INC set. |
|
120
|
|
|
|
|
|
|
# |
|
121
|
|
|
|
|
|
|
package Devel::ptkdb ; |
|
122
|
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
## |
|
124
|
|
|
|
|
|
|
## do this check once, rather than repeating the string comparison again and again |
|
125
|
|
|
|
|
|
|
## |
|
126
|
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
my $isWin32 = $^O eq 'MSWin32' ; |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
=head1 NAME |
|
131
|
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
Devel::ptkdb - Perl debugger using a Tk GUI |
|
133
|
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
ptkdb is a debugger for perl that uses perlTk for a user interface. |
|
137
|
|
|
|
|
|
|
Features include: |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
Hot Variable Inspection |
|
140
|
|
|
|
|
|
|
Breakpoint Control Panel |
|
141
|
|
|
|
|
|
|
Expression List |
|
142
|
|
|
|
|
|
|
Subroutine Tree |
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
=begin html |
|
146
|
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
=end html |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
152
|
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
To debug a script using ptkdb invoke perl like this: |
|
154
|
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
perl -d:ptkdb myscript.pl |
|
156
|
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
=head1 Usage |
|
158
|
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
perl -d:ptkdb myscript.pl |
|
160
|
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
=head1 Code Pane |
|
162
|
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
=over 4 |
|
164
|
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
=item Line Numbers |
|
166
|
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
Line numbers are presented on the left side of the window. Lines that |
|
168
|
|
|
|
|
|
|
have lines through them are not breakable. Lines that are plain text |
|
169
|
|
|
|
|
|
|
are breakable. Clicking on these line numbers will insert a |
|
170
|
|
|
|
|
|
|
breakpoint on that line and change the line number color to |
|
171
|
|
|
|
|
|
|
$ENV{'PTKDB_BRKPT_COLOR'} (Defaults to Red). Clicking on the number |
|
172
|
|
|
|
|
|
|
again will remove the breakpoint. If you disable the breakpoint with |
|
173
|
|
|
|
|
|
|
the controls on the BrkPt notebook page the color will change to |
|
174
|
|
|
|
|
|
|
$ENV{'PTKDB_DISABLEDBRKPT_COLOR'}(Defaults to Green). |
|
175
|
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
=item Cursor Motion |
|
177
|
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
If you place the cursor over a variable (i.e. $myVar, @myVar, or |
|
179
|
|
|
|
|
|
|
%myVar) and pause for a second the debugger will evaluate the current |
|
180
|
|
|
|
|
|
|
value of the variable and pop a balloon up with the evaluated |
|
181
|
|
|
|
|
|
|
result. I |
|
182
|
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
If Data::Dumper(standard with perl5.00502)is available it will be used |
|
184
|
|
|
|
|
|
|
to format the result. If there is an active selection, the text of |
|
185
|
|
|
|
|
|
|
that selection will be evaluated. |
|
186
|
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
=back |
|
188
|
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
=head1 Notebook Pane |
|
190
|
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
=over 2 |
|
192
|
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
=item Exprs |
|
194
|
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
This is a list of expressions that are evaluated each time the |
|
196
|
|
|
|
|
|
|
debugger stops. The results of the expresssion are presented |
|
197
|
|
|
|
|
|
|
heirarchically for expression that result in hashes or lists. Double |
|
198
|
|
|
|
|
|
|
clicking on such an expression will cause it to collapse; double |
|
199
|
|
|
|
|
|
|
clicking again will cause the expression to expand. Expressions are |
|
200
|
|
|
|
|
|
|
entered through B entry, or by Alt-E when text is |
|
201
|
|
|
|
|
|
|
selected in the code pane. |
|
202
|
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
The B entry, will take an expression, evaluate it, and |
|
204
|
|
|
|
|
|
|
replace the entries contents with the result. The result is also |
|
205
|
|
|
|
|
|
|
transfered to the 'clipboard' for pasting. |
|
206
|
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
=item Subs |
|
208
|
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
Displays a list of all the packages invoked with the script |
|
210
|
|
|
|
|
|
|
heirarchially. At the bottom of the heirarchy are the subroutines |
|
211
|
|
|
|
|
|
|
within the packages. Double click on a package to expand |
|
212
|
|
|
|
|
|
|
it. Subroutines are listed by their full package names. |
|
213
|
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
=item BrkPts |
|
215
|
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
Presents a list of the breakpoints current in use. The pushbutton |
|
217
|
|
|
|
|
|
|
allows a breakpoint to be 'disabled' without removing it. Expressions |
|
218
|
|
|
|
|
|
|
can be applied to the breakpoint. If the expression evaluates to be |
|
219
|
|
|
|
|
|
|
'true'(results in a defined value that is not 0) the debugger will |
|
220
|
|
|
|
|
|
|
stop the script. Pressing the 'Goto' button will set the text pane |
|
221
|
|
|
|
|
|
|
to that file and line where the breakpoint is set. Pressing the |
|
222
|
|
|
|
|
|
|
'Delete' button will delete the breakpoint. |
|
223
|
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
=back |
|
225
|
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
=head1 Menus |
|
227
|
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
=head2 File Menu |
|
229
|
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
=over |
|
231
|
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
=item About... |
|
233
|
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
Presents a dialog box telling you about the version of ptkdb. It |
|
235
|
|
|
|
|
|
|
recovers your OS name, version of perl, version of Tk, and some other |
|
236
|
|
|
|
|
|
|
information |
|
237
|
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
=item Open |
|
239
|
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
Presents a list of files that are part of the invoked perl |
|
241
|
|
|
|
|
|
|
script. Selecting a file from this list will present this file in the |
|
242
|
|
|
|
|
|
|
text window. |
|
243
|
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
=item Save Config... |
|
245
|
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
Requires Data::Dumper. Prompts for a filename to save the |
|
247
|
|
|
|
|
|
|
configuration to. Saves the breakpoints, expressions, eval text and |
|
248
|
|
|
|
|
|
|
window geometry. If the name given as the default is used and the |
|
249
|
|
|
|
|
|
|
script is reinvoked, this configuration will be reloaded |
|
250
|
|
|
|
|
|
|
automatically. |
|
251
|
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
B You may find this preferable to using |
|
253
|
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
=item Restore Config... |
|
255
|
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
Requires Data::Dumper. Prompts for a filename to restore a configuration saved with |
|
257
|
|
|
|
|
|
|
the "Save Config..." menu item. |
|
258
|
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
=item Goto Line... |
|
260
|
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
Prompts for a line number. Pressing the "Okay" button sends the window to the line number entered. |
|
262
|
|
|
|
|
|
|
item Find Text... |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
Prompts for text to search for. Options include forward search, |
|
265
|
|
|
|
|
|
|
backwards search, and regular expression searching. |
|
266
|
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
=item Quit |
|
268
|
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
Causes the debugger and the target script to exit. |
|
270
|
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
=back |
|
272
|
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
=head2 Control Menu |
|
274
|
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
=over |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
=item Run |
|
278
|
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
The debugger allows the script to run to the next breakpoint or until the script exits. |
|
280
|
|
|
|
|
|
|
item Run To Here |
|
281
|
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
Runs the debugger until it comes to wherever the insertion cursor |
|
283
|
|
|
|
|
|
|
in text window is placed. |
|
284
|
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
=item Set Breakpoint |
|
286
|
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
Sets a breakpoint on the line at the insertion cursor. |
|
288
|
|
|
|
|
|
|
item Clear Breakpoint |
|
289
|
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
Remove a breakpoint on the at the insertion cursor. |
|
291
|
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
=item Clear All Breakpoints |
|
293
|
|
|
|
|
|
|
|
|
294
|
|
|
|
|
|
|
Removes all current breakpoints |
|
295
|
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
=item Step Over |
|
297
|
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
Causes the debugger to step over the next line. If the line is a |
|
299
|
|
|
|
|
|
|
subroutine call it steps over the call, stopping when the subroutine |
|
300
|
|
|
|
|
|
|
returns. |
|
301
|
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
=item Step In |
|
303
|
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
Causes the debugger to step into the next line. If the line is a |
|
305
|
|
|
|
|
|
|
subroutine call it steps into the subroutine, stopping at the first |
|
306
|
|
|
|
|
|
|
executable line within the subroutine. |
|
307
|
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
=item Return |
|
309
|
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
Runs the script until it returns from the currently executing |
|
311
|
|
|
|
|
|
|
subroutine. |
|
312
|
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
=item Restart |
|
314
|
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
Saves the breakpoints and expressions in a temporary file and restarts |
|
316
|
|
|
|
|
|
|
the script from the beginning. CAUTION: This feature will not work |
|
317
|
|
|
|
|
|
|
properly with debugging of CGI Scripts. |
|
318
|
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
=item Stop On Warning |
|
320
|
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
When C<-w> is enabled the debugger will stop when warnings such as, "Use |
|
322
|
|
|
|
|
|
|
of uninitialized value at undef_warn.pl line N" are encountered. The debugger |
|
323
|
|
|
|
|
|
|
will stop on the NEXT line of execution since the error can't be detected |
|
324
|
|
|
|
|
|
|
until the current line has executed. |
|
325
|
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
This feature can be turned on at startup by adding: |
|
327
|
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
$DB::ptkdb::stop_on_warning = 1 ; |
|
329
|
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
to a .ptkdbrc file |
|
331
|
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
=back |
|
333
|
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
=head2 Data Menu |
|
335
|
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
=over |
|
337
|
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
=item Enter Expression |
|
339
|
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
When an expression is entered in the "Enter Expression:" text box, |
|
341
|
|
|
|
|
|
|
selecting this item will enter the expression into the expression |
|
342
|
|
|
|
|
|
|
list. Each time the debugger stops this expression will be evaluated |
|
343
|
|
|
|
|
|
|
and its result updated in the list window. |
|
344
|
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
=item Delete Expression |
|
346
|
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
Deletes the highlighted expression in the expression window. |
|
348
|
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
=item Delete All Expressions |
|
350
|
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
Delete all expressions in the expression window. |
|
352
|
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
=item Expression Eval Window |
|
354
|
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
Pops up a two pane window. Expressions of virtually unlimitted length |
|
356
|
|
|
|
|
|
|
can be entered in the top pane. Pressing the 'Eval' button will cause |
|
357
|
|
|
|
|
|
|
the expression to be evaluated and its placed in the lower pane. If |
|
358
|
|
|
|
|
|
|
Data::Dumper is available it will be used to format the resulting |
|
359
|
|
|
|
|
|
|
text. Undo is enabled for the text in the upper pane. |
|
360
|
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
HINT: You can enter multiple expressions by separating them with commas. |
|
362
|
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
=item Use Data::Dumper for Eval Window |
|
364
|
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
Enables or disables the use of Data::Dumper for formatting the results |
|
366
|
|
|
|
|
|
|
of expressions in the Eval window. |
|
367
|
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
=back |
|
369
|
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
=head2 Stack Menu |
|
371
|
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
Maintains a list of the current subroutine stack each time the |
|
373
|
|
|
|
|
|
|
debugger stops. Selecting an item from this menu will set the text in |
|
374
|
|
|
|
|
|
|
the code window to that particular subourtine entry point. |
|
375
|
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
=head2 Bookmarks Menu |
|
377
|
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
Maintains a list of bookmarks. The booksmarks are saved in ~/.ptkdb_bookmarks |
|
379
|
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
=over |
|
381
|
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
=item Add Bookmark |
|
383
|
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
Adds a bookmark to the bookmark list. |
|
385
|
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
=back |
|
387
|
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
=head1 Options |
|
389
|
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
Here is a list of the current active XResources options. Several of |
|
391
|
|
|
|
|
|
|
these can be overridden with environmental variables. Resources can be |
|
392
|
|
|
|
|
|
|
added to .Xresources or .Xdefaults depending on your X configuration. |
|
393
|
|
|
|
|
|
|
To enable these resources you must either restart your X server or use |
|
394
|
|
|
|
|
|
|
the xrdb -override resFile command. xfontsel can be used to select |
|
395
|
|
|
|
|
|
|
fonts. |
|
396
|
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
/* |
|
398
|
|
|
|
|
|
|
* Perl Tk Debugger XResources. |
|
399
|
|
|
|
|
|
|
* Note... These resources are subject to change. |
|
400
|
|
|
|
|
|
|
* |
|
401
|
|
|
|
|
|
|
* Use 'xfontsel' to select different fonts. |
|
402
|
|
|
|
|
|
|
* |
|
403
|
|
|
|
|
|
|
* Append these resource to ~/.Xdefaults | ~/.Xresources |
|
404
|
|
|
|
|
|
|
* and use xrdb -override ~/.Xdefaults | ~/.Xresources |
|
405
|
|
|
|
|
|
|
* to activate them. |
|
406
|
|
|
|
|
|
|
*/ |
|
407
|
|
|
|
|
|
|
/* Set Value to se to place scrollbars on the right side of windows |
|
408
|
|
|
|
|
|
|
CAUTION: extra whitespace at the end of the line is causing |
|
409
|
|
|
|
|
|
|
failures with Tk800.011. |
|
410
|
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
sw -> puts scrollbars on left, se puts scrollars on the right |
|
412
|
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
*/ |
|
414
|
|
|
|
|
|
|
ptkdb*scrollbars: sw |
|
415
|
|
|
|
|
|
|
/* controls where the code pane is oriented, down the left side, or across the top */ |
|
416
|
|
|
|
|
|
|
/* values can be set to left, right, top, bottom */ |
|
417
|
|
|
|
|
|
|
ptkdb*codeside: left |
|
418
|
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
/* |
|
420
|
|
|
|
|
|
|
* Background color for the balloon |
|
421
|
|
|
|
|
|
|
* CAUTION: For certain versions of Tk trailing |
|
422
|
|
|
|
|
|
|
* characters after the color produces an error |
|
423
|
|
|
|
|
|
|
*/ |
|
424
|
|
|
|
|
|
|
ptkdb.frame2.frame1.rotext.balloon.background: green |
|
425
|
|
|
|
|
|
|
ptkdb.frame2.frame1.rotext.balloon.font: fixed /* Hot Variable Balloon Font */ |
|
426
|
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
ptkdb.frame*font: fixed /* Menu Bar */ |
|
429
|
|
|
|
|
|
|
ptkdb.frame.menubutton.font: fixed /* File menu */ |
|
430
|
|
|
|
|
|
|
ptkdb.frame2.frame1.rotext.font: fixed /* Code Pane */ |
|
431
|
|
|
|
|
|
|
ptkdb.notebook.datapage.frame1.hlist.font: fixed /* Expression Notebook Page */ |
|
432
|
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
ptkdb.notebook.subspage*font: fixed /* Subroutine Notebook Page */ |
|
434
|
|
|
|
|
|
|
ptkdb.notebook.brkptspage*entry.font: fixed /* Delete Breakpoint Buttons */ |
|
435
|
|
|
|
|
|
|
ptkdb.notebook.brkptspage*button.font: fixed /* Breakpoint Expression Entries */ |
|
436
|
|
|
|
|
|
|
ptkdb.notebook.brkptspage*button1.font: fixed /* Breakpoint Expression Entries */ |
|
437
|
|
|
|
|
|
|
ptkdb.notebook.brkptspage*checkbutton.font: fixed /* Breakpoint Checkbuttons */ |
|
438
|
|
|
|
|
|
|
ptkdb.notebook.brkptspage*label.font: fixed /* Breakpoint Checkbuttons */ |
|
439
|
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
ptkdb.toplevel.frame.textundo.font: fixed /* Eval Expression Entry Window */ |
|
441
|
|
|
|
|
|
|
ptkdb.toplevel.frame1.text.font: fixed /* Eval Expression Results Window */ |
|
442
|
|
|
|
|
|
|
ptkdb.toplevel.button.font: fixed /* "Eval..." Button */ |
|
443
|
|
|
|
|
|
|
ptkdb.toplevel.button1.font: fixed /* "Clear Eval" Button */ |
|
444
|
|
|
|
|
|
|
ptkdb.toplevel.button2.font: fixed /* "Clear Results" Button */ |
|
445
|
|
|
|
|
|
|
ptkdb.toplevel.button3.font: fixed /* "Clear Dismiss" Button */ |
|
446
|
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
/* |
|
448
|
|
|
|
|
|
|
* Background color for where the debugger has stopped |
|
449
|
|
|
|
|
|
|
*/ |
|
450
|
|
|
|
|
|
|
ptkdb*stopcolor: blue |
|
451
|
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
/* |
|
453
|
|
|
|
|
|
|
* Background color for set breakpoints |
|
454
|
|
|
|
|
|
|
*/ |
|
455
|
|
|
|
|
|
|
ptkdb*breaktagcolor*background: yellow |
|
456
|
|
|
|
|
|
|
ptkdb*disabledbreaktagcolor*background: white |
|
457
|
|
|
|
|
|
|
/* |
|
458
|
|
|
|
|
|
|
* Font for where the debugger has stopped |
|
459
|
|
|
|
|
|
|
*/ |
|
460
|
|
|
|
|
|
|
ptkdb*stopfont: -*-fixed-bold-*-*-*-*-*-*-*-*-*-*-* |
|
461
|
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
/* |
|
463
|
|
|
|
|
|
|
* Background color for the search tag |
|
464
|
|
|
|
|
|
|
*/ |
|
465
|
|
|
|
|
|
|
ptkdb*searchtagcolor: green |
|
466
|
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
=head1 Environmental Variables |
|
468
|
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
=over 4 |
|
470
|
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
=item PTKDB_BRKPT_COLOR |
|
472
|
|
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
Sets the background color of a set breakpoint |
|
474
|
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
=item PTKDB_DISABLEDBRKPT_COLOR |
|
476
|
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
Sets the background color of a disabled breakpoint |
|
478
|
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
=item PTKDB_CODE_FONT |
|
480
|
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
Sets the font of the Text in the code pane. |
|
482
|
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
=item PTKDB_CODE_SIDE |
|
484
|
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
Sets which side the code pane is packed onto. Defaults to 'left'. |
|
486
|
|
|
|
|
|
|
Can be set to 'left', 'right', 'top', 'bottom'. |
|
487
|
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
Overrides the Xresource ptkdb*codeside: I. |
|
489
|
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
=item PTKDB_EXPRESSION_FONT |
|
491
|
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
Sets the font used in the expression notebook page. |
|
493
|
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
=item PTKDB_EVAL_FONT |
|
495
|
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
Sets the font used in the Expression Eval Window |
|
497
|
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
=item PTKDB_EVAL_DUMP_INDENT |
|
499
|
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
Sets the value used for Data::Dumper 'indent' setting. See man Data::Dumper |
|
501
|
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
=item PTKDB_SCROLLBARS_ONRIGHT |
|
503
|
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
A non-zero value Sets the scrollbars of all windows to be on the |
|
505
|
|
|
|
|
|
|
right side of the window. Useful for Windows users using ptkdb in an |
|
506
|
|
|
|
|
|
|
XWindows environment. |
|
507
|
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
=item PTKDB_LINENUMBER_FORMAT |
|
509
|
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
Sets the format of line numbers on the left side of the window. Default value is %05d. useful |
|
511
|
|
|
|
|
|
|
if you have a script that contains more than 99999 lines. |
|
512
|
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
=item PTKDB_DISPLAY |
|
514
|
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
Sets the X display that the ptkdb window will appear on when invoked. Useful for debugging CGI |
|
516
|
|
|
|
|
|
|
scripts on remote systems. |
|
517
|
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
=item PTKDB_BOOKMARKS_PATH |
|
519
|
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
Sets the path of the bookmarks file. Default is $ENV{'HOME'}/.ptkdb_bookmarks |
|
521
|
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
=item PTKDB_STOP_TAG_COLOR |
|
523
|
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
Sets the color that highlights the line where the debugger is stopped |
|
525
|
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
=back |
|
527
|
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
=head1 FILES |
|
529
|
|
|
|
|
|
|
|
|
530
|
|
|
|
|
|
|
=head2 .ptkdbrc |
|
531
|
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
If this file is present in ~/ or in the directory where perl is |
|
533
|
|
|
|
|
|
|
invoked the file will be read and executed as a perl script before the |
|
534
|
|
|
|
|
|
|
debugger makes its initial stop at startup. There are several 'api' |
|
535
|
|
|
|
|
|
|
calls that can be used with such scripts. There is an internal |
|
536
|
|
|
|
|
|
|
variable $DB::no_stop_at_start that may be set to non-zero to prevent |
|
537
|
|
|
|
|
|
|
the debugger from stopping at the first line of the script. This is |
|
538
|
|
|
|
|
|
|
useful for debugging CGI scripts. |
|
539
|
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
There is a system ptkdbrc file in $PREFIX/lib/perl5/$VERS/Devel/ptkdbrc |
|
541
|
|
|
|
|
|
|
|
|
542
|
|
|
|
|
|
|
=over 4 |
|
543
|
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
=item brkpt($fname, @lines) |
|
545
|
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
Sets breakspoints on the list of lines in $fname. A warning message |
|
547
|
|
|
|
|
|
|
is generated if a line is not breakable. |
|
548
|
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
=item condbrkpt($fname, @($line, $expr) ) |
|
550
|
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
Sets conditional breakpoints in $fname on pairs of $line and $expr. A |
|
552
|
|
|
|
|
|
|
warning message is generated if a line is not breakable. NOTE: the |
|
553
|
|
|
|
|
|
|
validity of the expression will not be determined until execution of |
|
554
|
|
|
|
|
|
|
that particular line. |
|
555
|
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
=item brkonsub(@names) |
|
557
|
|
|
|
|
|
|
|
|
558
|
|
|
|
|
|
|
Sets a breakpoint on each subroutine name listed. A warning message is |
|
559
|
|
|
|
|
|
|
generated if a subroutine does not exist. NOTE: for a script with no |
|
560
|
|
|
|
|
|
|
other packages the default package is "main::" and the subroutines |
|
561
|
|
|
|
|
|
|
would be "main::mySubs". |
|
562
|
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
=item brkonsub_regex(@regExprs) |
|
564
|
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
Uses the list of @regExprs as a list of regular expressions to set breakpoints. Sets breakpoints |
|
566
|
|
|
|
|
|
|
on every subroutine that matches any of the listed regular expressions. |
|
567
|
|
|
|
|
|
|
|
|
568
|
|
|
|
|
|
|
=item textTagConfigure(tag, ?option?, ?value?) |
|
569
|
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
Allows the user to format the text in the code window. The option |
|
571
|
|
|
|
|
|
|
value pairs are the same values as the option for the tagConfigure |
|
572
|
|
|
|
|
|
|
method documented in Tk::Text. Currently the following tags are in |
|
573
|
|
|
|
|
|
|
effect: |
|
574
|
|
|
|
|
|
|
|
|
575
|
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
'code' Format for code in the text pane |
|
577
|
|
|
|
|
|
|
'stoppt' Format applied to the line where the debugger is currently stopped |
|
578
|
|
|
|
|
|
|
'breakableLine' Format applied to line numbers where the code is 'breakable' |
|
579
|
|
|
|
|
|
|
'nonbreakableLine' Format applied to line numbers where the code is no breakable |
|
580
|
|
|
|
|
|
|
'breaksetLine' Format applied to line numbers were a breakpoint is set |
|
581
|
|
|
|
|
|
|
'breakdisabledLine' Format applied to line numbers were a disabled breakpoint is set |
|
582
|
|
|
|
|
|
|
'search_tag' Format applied to text when located by a search. |
|
583
|
|
|
|
|
|
|
|
|
584
|
|
|
|
|
|
|
Example: |
|
585
|
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
# |
|
587
|
|
|
|
|
|
|
# Turns off the overstrike on lines that you can't set a breakpoint on |
|
588
|
|
|
|
|
|
|
# and makes the text color yellow. |
|
589
|
|
|
|
|
|
|
# |
|
590
|
|
|
|
|
|
|
textTagConfigure('nonbreakableLine', -overstrike => 0, -foreground => "yellow") ; |
|
591
|
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
=item add_exprs(@exprList) |
|
593
|
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
Add a list of expressions to the 'Exprs' window. NOTE: use the single |
|
595
|
|
|
|
|
|
|
quote character \' to prevent the expression from being "evaluated" in |
|
596
|
|
|
|
|
|
|
the string context. |
|
597
|
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
Example: |
|
600
|
|
|
|
|
|
|
|
|
601
|
|
|
|
|
|
|
# |
|
602
|
|
|
|
|
|
|
# Adds the $_ and @_ expressions to the active list |
|
603
|
|
|
|
|
|
|
# |
|
604
|
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
add_exprs('$_', '@_') ; |
|
606
|
|
|
|
|
|
|
|
|
607
|
|
|
|
|
|
|
=back |
|
608
|
|
|
|
|
|
|
|
|
609
|
|
|
|
|
|
|
=head1 NOTES |
|
610
|
|
|
|
|
|
|
|
|
611
|
|
|
|
|
|
|
=head2 Debugging Other perlTk Applications |
|
612
|
|
|
|
|
|
|
|
|
613
|
|
|
|
|
|
|
ptkdb can be used to debug other perlTk applications if some cautions |
|
614
|
|
|
|
|
|
|
are observed. Basically, do not click the mouse in the application's |
|
615
|
|
|
|
|
|
|
window(s) when you've entered the debugger and do not click in the |
|
616
|
|
|
|
|
|
|
debugger's window(s) while the application is running. Doing either |
|
617
|
|
|
|
|
|
|
one is not necessarily fatal, but it can confuse things that are going |
|
618
|
|
|
|
|
|
|
on and produce unexpected results. |
|
619
|
|
|
|
|
|
|
|
|
620
|
|
|
|
|
|
|
Be aware that most perlTk applications have a central event loop. |
|
621
|
|
|
|
|
|
|
User actions, such as mouse clicks, key presses, window exposures, etc |
|
622
|
|
|
|
|
|
|
will generate 'events' that the script will process. When a perlTk |
|
623
|
|
|
|
|
|
|
application is running, its 'MainLoop' call will accept these events |
|
624
|
|
|
|
|
|
|
and then dispatch them to appropriate callbacks associated with the |
|
625
|
|
|
|
|
|
|
appropriate widgets. |
|
626
|
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
Ptkdb has its own event loop that runs whenever you've stopped at a |
|
628
|
|
|
|
|
|
|
breakpoint and entered the debugger. However, it can accept events |
|
629
|
|
|
|
|
|
|
that are generated by other perlTk windows and dispatch their |
|
630
|
|
|
|
|
|
|
callbacks. The problem here is that the application is supposed to be |
|
631
|
|
|
|
|
|
|
'stopped', and logically the application should not be able to process |
|
632
|
|
|
|
|
|
|
events. |
|
633
|
|
|
|
|
|
|
|
|
634
|
|
|
|
|
|
|
A future version of ptkdb will have an extension that will 'filter' |
|
635
|
|
|
|
|
|
|
events so that application events are not processed while the debugger |
|
636
|
|
|
|
|
|
|
is active, and debugger events will not be processed while the target |
|
637
|
|
|
|
|
|
|
script is active. |
|
638
|
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
=head2 Debugging CGI Scripts |
|
640
|
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
One advantage of ptkdb over the builtin debugger(-d) is that it can be |
|
642
|
|
|
|
|
|
|
used to debug CGI perl scripts as they run on a web server. Be sure |
|
643
|
|
|
|
|
|
|
that that your web server's perl instalation includes Tk. |
|
644
|
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
Change your |
|
646
|
|
|
|
|
|
|
|
|
647
|
|
|
|
|
|
|
#! /usr/local/bin/perl |
|
648
|
|
|
|
|
|
|
|
|
649
|
|
|
|
|
|
|
to |
|
650
|
|
|
|
|
|
|
|
|
651
|
|
|
|
|
|
|
#! /usr/local/bin/perl -d:ptkdb |
|
652
|
|
|
|
|
|
|
|
|
653
|
|
|
|
|
|
|
TIP: You can debug scripts remotely if you're using a unix based |
|
654
|
|
|
|
|
|
|
Xserver and where you are authoring the script has an Xserver. The |
|
655
|
|
|
|
|
|
|
Xserver can be another unix workstation, a Macintosh or Win32 platform |
|
656
|
|
|
|
|
|
|
with an appropriate XWindows package. In your script insert the |
|
657
|
|
|
|
|
|
|
following BEGIN subroutine: |
|
658
|
|
|
|
|
|
|
|
|
659
|
|
|
|
|
|
|
sub BEGIN { |
|
660
|
|
|
|
|
|
|
$ENV{'DISPLAY'} = "myHostname:0.0" ; |
|
661
|
|
|
|
|
|
|
} |
|
662
|
|
|
|
|
|
|
|
|
663
|
|
|
|
|
|
|
Be sure that your web server has permission to open windows on your |
|
664
|
|
|
|
|
|
|
Xserver (see the xhost manpage). |
|
665
|
|
|
|
|
|
|
|
|
666
|
|
|
|
|
|
|
Access your web page with your browswer and 'submit' the script as |
|
667
|
|
|
|
|
|
|
normal. The ptkdb window should appear on myHostname's monitor. At |
|
668
|
|
|
|
|
|
|
this point you can start debugging your script. Be aware that your |
|
669
|
|
|
|
|
|
|
browser may timeout waiting for the script to run. |
|
670
|
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
To expedite debugging you may want to setup your breakpoints in |
|
672
|
|
|
|
|
|
|
advance with a .ptkdbrc file and use the $DB::no_stop_at_start |
|
673
|
|
|
|
|
|
|
variable. NOTE: for debugging web scripts you may have to have the |
|
674
|
|
|
|
|
|
|
.ptkdbrc file installed in the server account's home directory (~www) |
|
675
|
|
|
|
|
|
|
or whatever username your webserver is running under. Also try |
|
676
|
|
|
|
|
|
|
installing a .ptkdbrc file in the same directory as the target script. |
|
677
|
|
|
|
|
|
|
|
|
678
|
|
|
|
|
|
|
=head1 KNOWN PROBLEMS |
|
679
|
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
=over |
|
681
|
|
|
|
|
|
|
|
|
682
|
|
|
|
|
|
|
=item I |
|
683
|
|
|
|
|
|
|
|
|
684
|
|
|
|
|
|
|
If the size of the right hand pane is too small the breakpoint controls |
|
685
|
|
|
|
|
|
|
are not visible. The breakpoints are still there, the window may have |
|
686
|
|
|
|
|
|
|
to be enlarged in order for them to be visible. |
|
687
|
|
|
|
|
|
|
|
|
688
|
|
|
|
|
|
|
=item Balloons and Tk400 |
|
689
|
|
|
|
|
|
|
|
|
690
|
|
|
|
|
|
|
The Balloons in Tk400 will not work with ptkdb. All other functions |
|
691
|
|
|
|
|
|
|
are supported, but the Balloons require Tk800 or higher. |
|
692
|
|
|
|
|
|
|
|
|
693
|
|
|
|
|
|
|
=back |
|
694
|
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
=head1 AUTHOR |
|
696
|
|
|
|
|
|
|
|
|
697
|
|
|
|
|
|
|
Andrew E. Page, aepage@users.sourceforge.net |
|
698
|
|
|
|
|
|
|
|
|
699
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS |
|
700
|
|
|
|
|
|
|
|
|
701
|
|
|
|
|
|
|
Matthew Persico For suggestions, and beta testing. |
|
702
|
|
|
|
|
|
|
|
|
703
|
|
|
|
|
|
|
=head1 BUG REPORTING |
|
704
|
|
|
|
|
|
|
|
|
705
|
|
|
|
|
|
|
Please report bugs through the following URL: |
|
706
|
|
|
|
|
|
|
|
|
707
|
|
|
|
|
|
|
http://sourceforge.net/tracker/?atid=437609&group_id=43854&func=browse |
|
708
|
|
|
|
|
|
|
|
|
709
|
|
|
|
|
|
|
=cut |
|
710
|
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
|
|
712
|
|
|
|
|
|
|
require 5.004 ; |
|
713
|
|
|
|
|
|
|
|
|
714
|
|
|
|
|
|
|
|
|
715
|
|
|
|
|
|
|
## |
|
716
|
|
|
|
|
|
|
## Perform a check to see if we have the Tk library, if not, attempt |
|
717
|
|
|
|
|
|
|
## to load it for the user |
|
718
|
|
|
|
|
|
|
## |
|
719
|
|
|
|
|
|
|
|
|
720
|
|
|
|
|
|
|
sub BEGIN { |
|
721
|
|
|
|
|
|
|
|
|
722
|
|
|
|
|
|
|
eval { |
|
723
|
|
|
|
|
|
|
require Tk ; |
|
724
|
|
|
|
|
|
|
} ; |
|
725
|
|
|
|
|
|
|
if( $@ ) { |
|
726
|
|
|
|
|
|
|
print << "__PTKDBTK_INSTALL__" ; |
|
727
|
|
|
|
|
|
|
*** |
|
728
|
|
|
|
|
|
|
*** The PerlTk library could not be found. Ptkdb requires the PerlTk library. |
|
729
|
|
|
|
|
|
|
*** |
|
730
|
|
|
|
|
|
|
Preferably Tk800.015 or better: |
|
731
|
|
|
|
|
|
|
|
|
732
|
|
|
|
|
|
|
In order to install this the following conditions must be met: |
|
733
|
|
|
|
|
|
|
|
|
734
|
|
|
|
|
|
|
1. You have to have access to a C compiler. |
|
735
|
|
|
|
|
|
|
2. You must have sufficient permissions to install the libraries on your system. |
|
736
|
|
|
|
|
|
|
|
|
737
|
|
|
|
|
|
|
To install PerlTk: |
|
738
|
|
|
|
|
|
|
|
|
739
|
|
|
|
|
|
|
a Download the Tk library source from http://www.perl.com/CPAN/modules/by-category/08_User_Interfaces/Tk |
|
740
|
|
|
|
|
|
|
b Uncompress the archive and run "perl Makefile.PL" |
|
741
|
|
|
|
|
|
|
c run "make install" |
|
742
|
|
|
|
|
|
|
|
|
743
|
|
|
|
|
|
|
If this process completes successfully ptkdb should be operational now. |
|
744
|
|
|
|
|
|
|
|
|
745
|
|
|
|
|
|
|
We can attempt to run the CPAN module for you. This will, after some questions, download |
|
746
|
|
|
|
|
|
|
and install the Tk library automatically. |
|
747
|
|
|
|
|
|
|
|
|
748
|
|
|
|
|
|
|
Would you like to run the CPAN module? (y/n) |
|
749
|
|
|
|
|
|
|
__PTKDBTK_INSTALL__ |
|
750
|
|
|
|
|
|
|
|
|
751
|
|
|
|
|
|
|
my $answer = ; |
|
752
|
|
|
|
|
|
|
chomp $answer ; |
|
753
|
|
|
|
|
|
|
if( $answer =~ /y|yes/i) { |
|
754
|
|
|
|
|
|
|
require CPAN ; |
|
755
|
|
|
|
|
|
|
CPAN::install Tk ; |
|
756
|
|
|
|
|
|
|
} # if |
|
757
|
|
|
|
|
|
|
|
|
758
|
|
|
|
|
|
|
} # if $@ |
|
759
|
|
|
|
|
|
|
|
|
760
|
|
|
|
|
|
|
|
|
761
|
|
|
|
|
|
|
} # end of sub BEGIN |
|
762
|
|
|
|
|
|
|
|
|
763
|
|
|
|
|
|
|
use Tk 800 ; |
|
764
|
|
|
|
|
|
|
use Data::Dumper ; |
|
765
|
|
|
|
|
|
|
use FileHandle ; |
|
766
|
|
|
|
|
|
|
|
|
767
|
|
|
|
|
|
|
require Tk::Dialog; |
|
768
|
|
|
|
|
|
|
require Tk::TextUndo ; |
|
769
|
|
|
|
|
|
|
require Tk::ROText; |
|
770
|
|
|
|
|
|
|
require Tk::NoteBook ; |
|
771
|
|
|
|
|
|
|
require Tk::HList ; |
|
772
|
|
|
|
|
|
|
require Tk::Table ; |
|
773
|
|
|
|
|
|
|
|
|
774
|
|
|
|
|
|
|
use vars qw(@dbline) ; |
|
775
|
|
|
|
|
|
|
|
|
776
|
|
|
|
|
|
|
use Config ; |
|
777
|
|
|
|
|
|
|
|
|
778
|
|
|
|
|
|
|
sub DoBugReport { |
|
779
|
|
|
|
|
|
|
my($str) = 'sourceforge.net/tracker/?atid=437609&group_id=43854&func=browse' ; |
|
780
|
|
|
|
|
|
|
my(@browsers) = qw/netscape mozilla/ ; |
|
781
|
|
|
|
|
|
|
my($fh, $pid, $sh) ; |
|
782
|
|
|
|
|
|
|
|
|
783
|
|
|
|
|
|
|
if( $isWin32 ) { |
|
784
|
|
|
|
|
|
|
$sh = '' ; |
|
785
|
|
|
|
|
|
|
@browsers = '"' . $ENV{'PROGRAMFILES'} . '\\Internet Explorer\\IEXPLORE.EXE' . '"' ; |
|
786
|
|
|
|
|
|
|
|
|
787
|
|
|
|
|
|
|
} |
|
788
|
|
|
|
|
|
|
else { |
|
789
|
|
|
|
|
|
|
$sh = 'sh' ; |
|
790
|
|
|
|
|
|
|
$str = "\'http://" . $str . "\'" ; |
|
791
|
|
|
|
|
|
|
} |
|
792
|
|
|
|
|
|
|
|
|
793
|
|
|
|
|
|
|
$fh = new FileHandle() ; |
|
794
|
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
for( @browsers ) { |
|
796
|
|
|
|
|
|
|
$pid = open($fh, "$sh $_ $str 2&> /dev/null |") ; |
|
797
|
|
|
|
|
|
|
sleep(2) ; |
|
798
|
|
|
|
|
|
|
waitpid $pid, 0 ; |
|
799
|
|
|
|
|
|
|
return if( $? == 0 ) ; |
|
800
|
|
|
|
|
|
|
} |
|
801
|
|
|
|
|
|
|
|
|
802
|
|
|
|
|
|
|
print "##\n" ; |
|
803
|
|
|
|
|
|
|
print "## Please submit a bug report through the following URL:\n" ; |
|
804
|
|
|
|
|
|
|
print '## http://sourceforge.net/tracker/?atid=437609&group_id=43854&func=browse', "\n" ; |
|
805
|
|
|
|
|
|
|
print "##\n" ; |
|
806
|
|
|
|
|
|
|
} |
|
807
|
|
|
|
|
|
|
|
|
808
|
|
|
|
|
|
|
# |
|
809
|
|
|
|
|
|
|
# Check to see if the package actually |
|
810
|
|
|
|
|
|
|
# exists. If it does import the routines |
|
811
|
|
|
|
|
|
|
# and return a true value ; |
|
812
|
|
|
|
|
|
|
# |
|
813
|
|
|
|
|
|
|
# NOTE: this needs to be above the 'BEGIN' subroutine, |
|
814
|
|
|
|
|
|
|
# otherwise it will not have been compiled by the time |
|
815
|
|
|
|
|
|
|
# that it is called by sub BEGIN. |
|
816
|
|
|
|
|
|
|
# |
|
817
|
|
|
|
|
|
|
sub check_avail { |
|
818
|
|
|
|
|
|
|
my ($mod, @list) = @_ ; |
|
819
|
|
|
|
|
|
|
|
|
820
|
|
|
|
|
|
|
eval { |
|
821
|
|
|
|
|
|
|
require $mod ; import $mod @list ; |
|
822
|
|
|
|
|
|
|
} ; |
|
823
|
|
|
|
|
|
|
|
|
824
|
|
|
|
|
|
|
return 0 if $@ ; |
|
825
|
|
|
|
|
|
|
return 1 ; |
|
826
|
|
|
|
|
|
|
|
|
827
|
|
|
|
|
|
|
} # end of check_avail |
|
828
|
|
|
|
|
|
|
|
|
829
|
|
|
|
|
|
|
sub BEGIN { |
|
830
|
|
|
|
|
|
|
|
|
831
|
|
|
|
|
|
|
$DB::on = 0 ; |
|
832
|
|
|
|
|
|
|
|
|
833
|
|
|
|
|
|
|
$DB::subroutine_depth = 0 ; # our subroutine depth counter |
|
834
|
|
|
|
|
|
|
$DB::step_over_depth = -1 ; |
|
835
|
|
|
|
|
|
|
|
|
836
|
|
|
|
|
|
|
# |
|
837
|
|
|
|
|
|
|
# the bindings and font specs for these operations have been placed here |
|
838
|
|
|
|
|
|
|
# to make them accessible to people who might want to customize the |
|
839
|
|
|
|
|
|
|
# operations. REF The 'bind.html' file, included in the perlTk FAQ has |
|
840
|
|
|
|
|
|
|
# a fairly good explanation of the binding syntax. |
|
841
|
|
|
|
|
|
|
# |
|
842
|
|
|
|
|
|
|
|
|
843
|
|
|
|
|
|
|
# |
|
844
|
|
|
|
|
|
|
# These lists of key bindings will be applied |
|
845
|
|
|
|
|
|
|
# to the "Step In", "Step Out", "Return" Commands |
|
846
|
|
|
|
|
|
|
# |
|
847
|
|
|
|
|
|
|
$Devel::ptkdb::pathSep = '\x00' ; |
|
848
|
|
|
|
|
|
|
$Devel::ptkdb::pathSepReplacement = "\0x01" ; |
|
849
|
|
|
|
|
|
|
|
|
850
|
|
|
|
|
|
|
@Devel::ptkdb::step_in_keys = ( '', '', '' ) ; # step into a subroutine |
|
851
|
|
|
|
|
|
|
@Devel::ptkdb::step_over_keys = ( '', '', '' ) ; # step over a subroutine |
|
852
|
|
|
|
|
|
|
@Devel::ptkdb::return_keys = ( '', '' ) ; # return from a subroutine |
|
853
|
|
|
|
|
|
|
@Devel::ptkdb::toggle_breakpt_keys = ( '' ) ; # set or unset a breakpoint |
|
854
|
|
|
|
|
|
|
|
|
855
|
|
|
|
|
|
|
# Fonts used in the displays |
|
856
|
|
|
|
|
|
|
|
|
857
|
|
|
|
|
|
|
# |
|
858
|
|
|
|
|
|
|
# NOTE: The environmental variable syntax here works like this: |
|
859
|
|
|
|
|
|
|
# $ENV{'NAME'} accesses the environmental variable "NAME" |
|
860
|
|
|
|
|
|
|
# |
|
861
|
|
|
|
|
|
|
# $ENV{'NAME'} || 'string' results in $ENV{'NAME'} or 'string' if $ENV{'NAME'} is not defined. |
|
862
|
|
|
|
|
|
|
# |
|
863
|
|
|
|
|
|
|
# |
|
864
|
|
|
|
|
|
|
|
|
865
|
|
|
|
|
|
|
@Devel::ptkdb::button_font = $ENV{'PTKDB_BUTTON_FONT'} ? ( "-font" => $ENV{'PTKDB_CODE_FONT'} ) : () ; # font for buttons |
|
866
|
|
|
|
|
|
|
@Devel::ptkdb::code_text_font = $ENV{'PTKDB_CODE_FONT'} ? ( "-font" => $ENV{'PTKDB_CODE_FONT'} ) : () ; |
|
867
|
|
|
|
|
|
|
|
|
868
|
|
|
|
|
|
|
@Devel::ptkdb::expression_text_font = $ENV{'PTKDB_EXPRESSION_FONT'} ? ( "-font" => $ENV{'PTKDB_EXPRESSION_FONT'} ) : () ; |
|
869
|
|
|
|
|
|
|
@Devel::ptkdb::eval_text_font = $ENV{'PTKDB_EVAL_FONT'} ? ( -font => $ENV{'PTKDB_EVAL_FONT'} ) : () ; # text for the expression eval window |
|
870
|
|
|
|
|
|
|
|
|
871
|
|
|
|
|
|
|
$Devel::ptkdb::eval_dump_indent = $ENV{'PTKDB_EVAL_DUMP_INDENT'} || 1 ; |
|
872
|
|
|
|
|
|
|
|
|
873
|
|
|
|
|
|
|
# |
|
874
|
|
|
|
|
|
|
# Windows users are more used to having scroll bars on the right. |
|
875
|
|
|
|
|
|
|
# If they've set PTKDB_SCROLLBARS_ONRIGHT to a non-zero value |
|
876
|
|
|
|
|
|
|
# this will configure our scrolled windows with scrollbars on the right |
|
877
|
|
|
|
|
|
|
# |
|
878
|
|
|
|
|
|
|
# this can also be done by setting: |
|
879
|
|
|
|
|
|
|
# |
|
880
|
|
|
|
|
|
|
# ptkdb*scrollbars: se |
|
881
|
|
|
|
|
|
|
# |
|
882
|
|
|
|
|
|
|
# in the .Xdefaults/.Xresources file on X based systems |
|
883
|
|
|
|
|
|
|
# |
|
884
|
|
|
|
|
|
|
if( exists $ENV{'PTKDB_SCROLLBARS_ONRIGHT'} && $ENV{'PTKDB_SCROLLBARS_ONRIGHT'} ) { |
|
885
|
|
|
|
|
|
|
@Devel::ptkdb::scrollbar_cfg = ('-scrollbars' => 'se') ; |
|
886
|
|
|
|
|
|
|
} |
|
887
|
|
|
|
|
|
|
else { |
|
888
|
|
|
|
|
|
|
@Devel::ptkdb::scrollbar_cfg = ( ) ; |
|
889
|
|
|
|
|
|
|
} |
|
890
|
|
|
|
|
|
|
|
|
891
|
|
|
|
|
|
|
# |
|
892
|
|
|
|
|
|
|
# Controls how far an expression result will be 'decomposed'. Setting it |
|
893
|
|
|
|
|
|
|
# to 0 will take it down only one level, setting it to -1 will make it |
|
894
|
|
|
|
|
|
|
# decompose it all the way down. However, if you have a situation where |
|
895
|
|
|
|
|
|
|
# an element is a ref back to the array or a root of the array |
|
896
|
|
|
|
|
|
|
# you could hang the debugger by making it recursively evaluate an expression |
|
897
|
|
|
|
|
|
|
# |
|
898
|
|
|
|
|
|
|
$Devel::ptkdb::expr_depth = -1 ; |
|
899
|
|
|
|
|
|
|
$Devel::ptkdb::add_expr_depth = 1 ; # how much further to expand an expression when clicked |
|
900
|
|
|
|
|
|
|
|
|
901
|
|
|
|
|
|
|
$Devel::ptkdb::linenumber_format = $ENV{'PTKDB_LINENUMBER_FORMAT'} || "%05d " ; |
|
902
|
|
|
|
|
|
|
$Devel::ptkdb::linenumber_length = 5 ; |
|
903
|
|
|
|
|
|
|
|
|
904
|
|
|
|
|
|
|
$Devel::ptkdb::linenumber_offset = length sprintf($Devel::ptkdb::linenumber_format, 0) ; |
|
905
|
|
|
|
|
|
|
$Devel::ptkdb::linenumber_offset -= 1 ; |
|
906
|
|
|
|
|
|
|
|
|
907
|
|
|
|
|
|
|
# |
|
908
|
|
|
|
|
|
|
# Check to see if "Data Dumper" is available |
|
909
|
|
|
|
|
|
|
# if it is we can save breakpoints and other |
|
910
|
|
|
|
|
|
|
# various "functions". This call will also |
|
911
|
|
|
|
|
|
|
# load the subroutines needed. |
|
912
|
|
|
|
|
|
|
# |
|
913
|
|
|
|
|
|
|
$Devel::ptkdb::DataDumperAvailable = 1 ; # assuming that it is now |
|
914
|
|
|
|
|
|
|
$Devel::ptkdb::useDataDumperForEval = $Devel::ptkdb::DataDumperAvailable ; |
|
915
|
|
|
|
|
|
|
|
|
916
|
|
|
|
|
|
|
# |
|
917
|
|
|
|
|
|
|
# DB Options (things not directly involving the window) |
|
918
|
|
|
|
|
|
|
# |
|
919
|
|
|
|
|
|
|
|
|
920
|
|
|
|
|
|
|
# Flag to disable us from intercepting $SIG{'INT'} |
|
921
|
|
|
|
|
|
|
|
|
922
|
|
|
|
|
|
|
$DB::sigint_disable = defined $ENV{'PTKDB_SIGINT_DISABLE'} && $ENV{'PTKDB_SIGINT_DISABLE'} ; |
|
923
|
|
|
|
|
|
|
# |
|
924
|
|
|
|
|
|
|
# Possibly for debugging perl CGI Web scripts on |
|
925
|
|
|
|
|
|
|
# remote machines. |
|
926
|
|
|
|
|
|
|
# |
|
927
|
|
|
|
|
|
|
$ENV{'DISPLAY'} = $ENV{'PTKDB_DISPLAY'} if exists $ENV{'PTKDB_DISPLAY'} ; |
|
928
|
|
|
|
|
|
|
|
|
929
|
|
|
|
|
|
|
} # end of BEGIN |
|
930
|
|
|
|
|
|
|
|
|
931
|
|
|
|
|
|
|
## |
|
932
|
|
|
|
|
|
|
## subroutine provided to the user for initializing |
|
933
|
|
|
|
|
|
|
## files in .ptkdbrc |
|
934
|
|
|
|
|
|
|
## |
|
935
|
|
|
|
|
|
|
sub brkpt { |
|
936
|
|
|
|
|
|
|
my ($fName, @idx) = @_ ; |
|
937
|
|
|
|
|
|
|
my($offset) ; |
|
938
|
|
|
|
|
|
|
local(*dbline) = $main::{'_<' . $fName} ; |
|
939
|
|
|
|
|
|
|
|
|
940
|
|
|
|
|
|
|
$offset = $dbline[1] =~ /use\s+.*Devel::_?ptkdb/ ? 1 : 0 ; |
|
941
|
|
|
|
|
|
|
|
|
942
|
|
|
|
|
|
|
for( @idx ) { |
|
943
|
|
|
|
|
|
|
if( !&DB::checkdbline($fName, $_ + $offset) ) { |
|
944
|
|
|
|
|
|
|
my ($package, $filename, $line) = caller ; |
|
945
|
|
|
|
|
|
|
print "$filename:$line: $fName line $_ is not breakable\n" ; |
|
946
|
|
|
|
|
|
|
next ; |
|
947
|
|
|
|
|
|
|
} |
|
948
|
|
|
|
|
|
|
$DB::window->insertBreakpoint($fName, $_, 1) ; # insert a simple breakpoint |
|
949
|
|
|
|
|
|
|
} |
|
950
|
|
|
|
|
|
|
} # end of brkpt |
|
951
|
|
|
|
|
|
|
|
|
952
|
|
|
|
|
|
|
# |
|
953
|
|
|
|
|
|
|
# Set conditional breakpoint(s) |
|
954
|
|
|
|
|
|
|
# |
|
955
|
|
|
|
|
|
|
sub condbrkpt { |
|
956
|
|
|
|
|
|
|
my ($fname) = shift ; |
|
957
|
|
|
|
|
|
|
my($offset) ; |
|
958
|
|
|
|
|
|
|
local(*dbline) = $main::{'_<' . $fname} ; |
|
959
|
|
|
|
|
|
|
|
|
960
|
|
|
|
|
|
|
$offset = $dbline[1] =~ /use\s+.*Devel::_?ptkdb/ ? 1 : 0 ; |
|
961
|
|
|
|
|
|
|
|
|
962
|
|
|
|
|
|
|
while( @_ ) { # arg loop |
|
963
|
|
|
|
|
|
|
my($index, $expr) = splice @_, 0, 2 ; # take args 2 at a time |
|
964
|
|
|
|
|
|
|
|
|
965
|
|
|
|
|
|
|
if( !&DB::checkdbline($fname, $index + $offset) ) { |
|
966
|
|
|
|
|
|
|
my ($package, $filename, $line) = caller ; |
|
967
|
|
|
|
|
|
|
print "$filename:$line: $fname line $index is not breakable\n" ; |
|
968
|
|
|
|
|
|
|
next ; |
|
969
|
|
|
|
|
|
|
} |
|
970
|
|
|
|
|
|
|
$DB::window->insertBreakpoint($fname, $index, 1, $expr) ; # insert a simple breakpoint |
|
971
|
|
|
|
|
|
|
} # end of arg loop |
|
972
|
|
|
|
|
|
|
|
|
973
|
|
|
|
|
|
|
} # end of conditionalbrkpt |
|
974
|
|
|
|
|
|
|
|
|
975
|
|
|
|
|
|
|
sub brkonsub { |
|
976
|
|
|
|
|
|
|
my(@names) = @_ ; |
|
977
|
|
|
|
|
|
|
|
|
978
|
|
|
|
|
|
|
for( @names ) { |
|
979
|
|
|
|
|
|
|
|
|
980
|
|
|
|
|
|
|
# get the filename and line number range of the target subroutine |
|
981
|
|
|
|
|
|
|
|
|
982
|
|
|
|
|
|
|
if( !exists $DB::sub{$_} ) { |
|
983
|
|
|
|
|
|
|
print "No subroutine $_. Try main::$_\n" ; |
|
984
|
|
|
|
|
|
|
next ; |
|
985
|
|
|
|
|
|
|
} |
|
986
|
|
|
|
|
|
|
|
|
987
|
|
|
|
|
|
|
$DB::sub{$_} =~ /(.*):([0-9]+)-([0-9]+)$/o ; # file name will be in $1, start line $2, end line $3 |
|
988
|
|
|
|
|
|
|
|
|
989
|
|
|
|
|
|
|
for( $2..$3 ) { |
|
990
|
|
|
|
|
|
|
next unless &DB::checkdbline($1, $_) ; |
|
991
|
|
|
|
|
|
|
$DB::window->insertBreakpoint($1, $_, 1) ; |
|
992
|
|
|
|
|
|
|
last ; # only need the one breakpoint |
|
993
|
|
|
|
|
|
|
} |
|
994
|
|
|
|
|
|
|
} # end of name loop |
|
995
|
|
|
|
|
|
|
|
|
996
|
|
|
|
|
|
|
} # end of brkonsub |
|
997
|
|
|
|
|
|
|
|
|
998
|
|
|
|
|
|
|
# |
|
999
|
|
|
|
|
|
|
# set breakpoints on subroutines matching a regular |
|
1000
|
|
|
|
|
|
|
# expression |
|
1001
|
|
|
|
|
|
|
# |
|
1002
|
|
|
|
|
|
|
sub brkonsub_regex { |
|
1003
|
|
|
|
|
|
|
my(@regexps) = @_ ; |
|
1004
|
|
|
|
|
|
|
my($regexp, @subList) ; |
|
1005
|
|
|
|
|
|
|
|
|
1006
|
|
|
|
|
|
|
# |
|
1007
|
|
|
|
|
|
|
# accumulate matching subroutines |
|
1008
|
|
|
|
|
|
|
# |
|
1009
|
|
|
|
|
|
|
foreach $regexp ( @regexps ) { |
|
1010
|
|
|
|
|
|
|
study $regexp ; |
|
1011
|
|
|
|
|
|
|
push @subList, grep /$regexp/, keys %DB::sub ; |
|
1012
|
|
|
|
|
|
|
} # end of brkonsub_regex |
|
1013
|
|
|
|
|
|
|
|
|
1014
|
|
|
|
|
|
|
brkonsub(@subList) ; # set breakpoints on matching subroutines |
|
1015
|
|
|
|
|
|
|
|
|
1016
|
|
|
|
|
|
|
} # end of brkonsub_regex |
|
1017
|
|
|
|
|
|
|
|
|
1018
|
|
|
|
|
|
|
# |
|
1019
|
|
|
|
|
|
|
# Allow the user Access to our tag configurations |
|
1020
|
|
|
|
|
|
|
# |
|
1021
|
|
|
|
|
|
|
sub textTagConfigure { |
|
1022
|
|
|
|
|
|
|
my ($tag, @config) = @_ ; |
|
1023
|
|
|
|
|
|
|
|
|
1024
|
|
|
|
|
|
|
$DB::window->{'text'}->tagConfigure($tag, @config) ; |
|
1025
|
|
|
|
|
|
|
|
|
1026
|
|
|
|
|
|
|
} # end of textTagConfigure |
|
1027
|
|
|
|
|
|
|
|
|
1028
|
|
|
|
|
|
|
## |
|
1029
|
|
|
|
|
|
|
## Change the tabs in the text field |
|
1030
|
|
|
|
|
|
|
## |
|
1031
|
|
|
|
|
|
|
sub setTabs { |
|
1032
|
|
|
|
|
|
|
|
|
1033
|
|
|
|
|
|
|
$DB::window->{'text'}->configure(-tabs => [ @_ ]) ; |
|
1034
|
|
|
|
|
|
|
|
|
1035
|
|
|
|
|
|
|
} |
|
1036
|
|
|
|
|
|
|
|
|
1037
|
|
|
|
|
|
|
# |
|
1038
|
|
|
|
|
|
|
# User .ptkdbrc API |
|
1039
|
|
|
|
|
|
|
# allows the user to add expressions to |
|
1040
|
|
|
|
|
|
|
# the expression list window. |
|
1041
|
|
|
|
|
|
|
# |
|
1042
|
|
|
|
|
|
|
sub add_exprs { |
|
1043
|
|
|
|
|
|
|
push @{$DB::window->{'expr_list'}}, map { 'expr' => $_, 'depth' => $Devel::ptkdb::expr_depth }, @_ ; |
|
1044
|
|
|
|
|
|
|
} # end of add_exprs |
|
1045
|
|
|
|
|
|
|
|
|
1046
|
|
|
|
|
|
|
|
|
1047
|
|
|
|
|
|
|
## |
|
1048
|
|
|
|
|
|
|
## register a subroutine reference that will be called whenever |
|
1049
|
|
|
|
|
|
|
## ptkdb sets up it's windows |
|
1050
|
|
|
|
|
|
|
## |
|
1051
|
|
|
|
|
|
|
sub register_user_window_init { |
|
1052
|
|
|
|
|
|
|
push @{$DB::window->{'user_window_init_list'}}, @_ ; |
|
1053
|
|
|
|
|
|
|
} # end of register_user_window_init |
|
1054
|
|
|
|
|
|
|
|
|
1055
|
|
|
|
|
|
|
## |
|
1056
|
|
|
|
|
|
|
## register a subroutine reference that will be called whenever |
|
1057
|
|
|
|
|
|
|
## ptkdb enters from code |
|
1058
|
|
|
|
|
|
|
## |
|
1059
|
|
|
|
|
|
|
sub register_user_DB_entry { |
|
1060
|
|
|
|
|
|
|
push @{$DB::window->{'user_window_DB_entry_list'}}, @_ ; |
|
1061
|
|
|
|
|
|
|
} # end of register_user_DB_entry |
|
1062
|
|
|
|
|
|
|
|
|
1063
|
|
|
|
|
|
|
sub get_notebook_widget { |
|
1064
|
|
|
|
|
|
|
return $DB::window->{'notebook'} ; |
|
1065
|
|
|
|
|
|
|
} # end of get_notebook_widget |
|
1066
|
|
|
|
|
|
|
|
|
1067
|
|
|
|
|
|
|
|
|
1068
|
|
|
|
|
|
|
# |
|
1069
|
|
|
|
|
|
|
# Run files provided by the user |
|
1070
|
|
|
|
|
|
|
# |
|
1071
|
|
|
|
|
|
|
sub do_user_init_files { |
|
1072
|
|
|
|
|
|
|
use vars qw($dbg_window) ; |
|
1073
|
|
|
|
|
|
|
local $dbg_window = shift ; |
|
1074
|
|
|
|
|
|
|
|
|
1075
|
|
|
|
|
|
|
eval { |
|
1076
|
|
|
|
|
|
|
do "$Config{'installprivlib'}/Devel/ptkdbrc" ; |
|
1077
|
|
|
|
|
|
|
} if -e "$Config{'installprivlib'}/Devel/ptkdbrc" ; |
|
1078
|
|
|
|
|
|
|
|
|
1079
|
|
|
|
|
|
|
if( $@ ) { |
|
1080
|
|
|
|
|
|
|
print "System init file $Config{'installprivlib'}/ptkdbrc failed: $@\n" ; |
|
1081
|
|
|
|
|
|
|
} |
|
1082
|
|
|
|
|
|
|
|
|
1083
|
|
|
|
|
|
|
eval { |
|
1084
|
|
|
|
|
|
|
do "$ENV{'HOME'}/.ptkdbrc" ; |
|
1085
|
|
|
|
|
|
|
} if exists $ENV{'HOME'} && -e "$ENV{'HOME'}/.ptkdbrc" ; |
|
1086
|
|
|
|
|
|
|
|
|
1087
|
|
|
|
|
|
|
if( $@ ) { |
|
1088
|
|
|
|
|
|
|
print "User init file $ENV{'HOME'}/.ptkdbrc failed: $@\n" ; |
|
1089
|
|
|
|
|
|
|
} |
|
1090
|
|
|
|
|
|
|
|
|
1091
|
|
|
|
|
|
|
eval { |
|
1092
|
|
|
|
|
|
|
do ".ptkdbrc" ; |
|
1093
|
|
|
|
|
|
|
} if -e ".ptkdbrc" ; |
|
1094
|
|
|
|
|
|
|
|
|
1095
|
|
|
|
|
|
|
if( $@ ) { |
|
1096
|
|
|
|
|
|
|
print "User init file .ptkdbrc failed: $@\n" ; |
|
1097
|
|
|
|
|
|
|
} |
|
1098
|
|
|
|
|
|
|
|
|
1099
|
|
|
|
|
|
|
&set_stop_on_warning() ; |
|
1100
|
|
|
|
|
|
|
} |
|
1101
|
|
|
|
|
|
|
|
|
1102
|
|
|
|
|
|
|
# |
|
1103
|
|
|
|
|
|
|
# Constructor for our Devel::ptkdb |
|
1104
|
|
|
|
|
|
|
# |
|
1105
|
|
|
|
|
|
|
sub new { |
|
1106
|
|
|
|
|
|
|
my($type) = @_ ; |
|
1107
|
|
|
|
|
|
|
my($self) = {} ; |
|
1108
|
|
|
|
|
|
|
|
|
1109
|
|
|
|
|
|
|
bless $self, $type ; |
|
1110
|
|
|
|
|
|
|
|
|
1111
|
|
|
|
|
|
|
# Current position of the executing program |
|
1112
|
|
|
|
|
|
|
|
|
1113
|
|
|
|
|
|
|
$self->{DisableOnLeave} = [] ; # List o' Widgets to disable when leaving the debugger |
|
1114
|
|
|
|
|
|
|
|
|
1115
|
|
|
|
|
|
|
$self->{current_file} = "" ; |
|
1116
|
|
|
|
|
|
|
$self->{current_line} = -1 ; # initial value indicating we haven't set our line/tag |
|
1117
|
|
|
|
|
|
|
$self->{window_pos_offset} = 10 ; # when we enter how far from the top of the text are we positioned down |
|
1118
|
|
|
|
|
|
|
$self->{search_start} = "0.0" ; |
|
1119
|
|
|
|
|
|
|
$self->{fwdOrBack} = 1 ; |
|
1120
|
|
|
|
|
|
|
$self->{BookMarksPath} = $ENV{'PTKDB_BOOKMARKS_PATH'} || "$ENV{'HOME'}/.ptkdb_bookmarks" || '.ptkdb_bookmarks' ; |
|
1121
|
|
|
|
|
|
|
|
|
1122
|
|
|
|
|
|
|
$self->{'expr_list'} = [] ; # list of expressions to eval in our window fields: {'expr'} The expr itself {'depth'} expansion depth |
|
1123
|
|
|
|
|
|
|
|
|
1124
|
|
|
|
|
|
|
|
|
1125
|
|
|
|
|
|
|
$self->{'brkPtCnt'} = 0 ; |
|
1126
|
|
|
|
|
|
|
$self->{'brkPtSlots'} = [] ; # open slots for adding breakpoints to the table |
|
1127
|
|
|
|
|
|
|
|
|
1128
|
|
|
|
|
|
|
$self->{'main_window'} = undef ; |
|
1129
|
|
|
|
|
|
|
|
|
1130
|
|
|
|
|
|
|
$self->{'user_window_init_list'} = [] ; |
|
1131
|
|
|
|
|
|
|
$self->{'user_window_DB_entry_list'} = [] ; |
|
1132
|
|
|
|
|
|
|
|
|
1133
|
|
|
|
|
|
|
$self->{'subs_list_cnt'} = 0 ; |
|
1134
|
|
|
|
|
|
|
|
|
1135
|
|
|
|
|
|
|
$self->setup_main_window() ; |
|
1136
|
|
|
|
|
|
|
|
|
1137
|
|
|
|
|
|
|
return $self ; |
|
1138
|
|
|
|
|
|
|
|
|
1139
|
|
|
|
|
|
|
} # end of new |
|
1140
|
|
|
|
|
|
|
|
|
1141
|
|
|
|
|
|
|
sub setup_main_window { |
|
1142
|
|
|
|
|
|
|
my($self) = @_ ; |
|
1143
|
|
|
|
|
|
|
|
|
1144
|
|
|
|
|
|
|
# Main Window |
|
1145
|
|
|
|
|
|
|
|
|
1146
|
|
|
|
|
|
|
|
|
1147
|
|
|
|
|
|
|
$self->{main_window} = MainWindow->new() ; |
|
1148
|
|
|
|
|
|
|
$self->{main_window}->geometry($ENV{'PTKDB_GEOMETRY'} || "800x600") ; |
|
1149
|
|
|
|
|
|
|
|
|
1150
|
|
|
|
|
|
|
$self->setup_options() ; # must be done after MainWindow and before other frames are setup |
|
1151
|
|
|
|
|
|
|
|
|
1152
|
|
|
|
|
|
|
$self->{main_window}->bind('', \&DB::dbint_handler) ; |
|
1153
|
|
|
|
|
|
|
|
|
1154
|
|
|
|
|
|
|
# |
|
1155
|
|
|
|
|
|
|
# Bind our 'quit' routine to a close command from the window manager (Alt-F4) |
|
1156
|
|
|
|
|
|
|
# |
|
1157
|
|
|
|
|
|
|
$self->{main_window}->protocol('WM_DELETE_WINDOW', sub { $self->close_ptkdb_window() ; } ) ; |
|
1158
|
|
|
|
|
|
|
|
|
1159
|
|
|
|
|
|
|
# Menu bar |
|
1160
|
|
|
|
|
|
|
|
|
1161
|
|
|
|
|
|
|
$self->setup_menu_bar() ; |
|
1162
|
|
|
|
|
|
|
|
|
1163
|
|
|
|
|
|
|
# |
|
1164
|
|
|
|
|
|
|
# setup Frames |
|
1165
|
|
|
|
|
|
|
# |
|
1166
|
|
|
|
|
|
|
# Setup our Code, Data, and breakpoints |
|
1167
|
|
|
|
|
|
|
|
|
1168
|
|
|
|
|
|
|
$self->setup_frames() ; |
|
1169
|
|
|
|
|
|
|
|
|
1170
|
|
|
|
|
|
|
} |
|
1171
|
|
|
|
|
|
|
|
|
1172
|
|
|
|
|
|
|
# |
|
1173
|
|
|
|
|
|
|
# Check for changes to the bookmarks and quit |
|
1174
|
|
|
|
|
|
|
# |
|
1175
|
|
|
|
|
|
|
sub DoQuit { |
|
1176
|
|
|
|
|
|
|
my($self) = @_ ; |
|
1177
|
|
|
|
|
|
|
|
|
1178
|
|
|
|
|
|
|
$self->save_bookmarks($self->{BookMarksPath}) if $Devel::ptkdb::DataDumperAvailable && $self->{'bookmarks_changed'}; |
|
1179
|
|
|
|
|
|
|
$self->{main_window}->destroy if $self->{main_window} ; |
|
1180
|
|
|
|
|
|
|
$self->{main_window} = undef if defined $self->{main_window} ; |
|
1181
|
|
|
|
|
|
|
|
|
1182
|
|
|
|
|
|
|
exit ; |
|
1183
|
|
|
|
|
|
|
} |
|
1184
|
|
|
|
|
|
|
|
|
1185
|
|
|
|
|
|
|
# |
|
1186
|
|
|
|
|
|
|
# This supports the File -> Open menu item |
|
1187
|
|
|
|
|
|
|
# We create a new window and list all of the files |
|
1188
|
|
|
|
|
|
|
# that are contained in the program. We also |
|
1189
|
|
|
|
|
|
|
# pick up all of the perlTk files that are supporting |
|
1190
|
|
|
|
|
|
|
# the debugger. |
|
1191
|
|
|
|
|
|
|
# |
|
1192
|
|
|
|
|
|
|
sub DoOpen { |
|
1193
|
|
|
|
|
|
|
my $self = shift ; |
|
1194
|
|
|
|
|
|
|
my ($topLevel, $listBox, $frame, $selectedFile, @fList) ; |
|
1195
|
|
|
|
|
|
|
|
|
1196
|
|
|
|
|
|
|
# |
|
1197
|
|
|
|
|
|
|
# subroutine we call when we've selected a file |
|
1198
|
|
|
|
|
|
|
# |
|
1199
|
|
|
|
|
|
|
|
|
1200
|
|
|
|
|
|
|
my $chooseSub = sub { $selectedFile = $listBox->get('active') ; |
|
1201
|
|
|
|
|
|
|
print "attempting to open $selectedFile\n" ; |
|
1202
|
|
|
|
|
|
|
$DB::window->set_file($selectedFile, 0) ; |
|
1203
|
|
|
|
|
|
|
destroy $topLevel ; |
|
1204
|
|
|
|
|
|
|
} ; |
|
1205
|
|
|
|
|
|
|
|
|
1206
|
|
|
|
|
|
|
# |
|
1207
|
|
|
|
|
|
|
# Take the list the files and resort it. |
|
1208
|
|
|
|
|
|
|
# we put all of the local files first, and |
|
1209
|
|
|
|
|
|
|
# then list all of the system libraries. |
|
1210
|
|
|
|
|
|
|
# |
|
1211
|
|
|
|
|
|
|
@fList = sort { |
|
1212
|
|
|
|
|
|
|
# sort comparison function block |
|
1213
|
|
|
|
|
|
|
my $fa = substr($a, 0, 1) ; |
|
1214
|
|
|
|
|
|
|
my $fb = substr($b, 0, 1) ; |
|
1215
|
|
|
|
|
|
|
|
|
1216
|
|
|
|
|
|
|
return $a cmp $b if ($fa eq '/') && ($fb eq '/') ; |
|
1217
|
|
|
|
|
|
|
|
|
1218
|
|
|
|
|
|
|
return -1 if ($fb eq '/') && ($fa ne '/') ; |
|
1219
|
|
|
|
|
|
|
return 1 if ($fa eq '/' ) && ($fb ne '/') ; |
|
1220
|
|
|
|
|
|
|
|
|
1221
|
|
|
|
|
|
|
return $a cmp $b ; |
|
1222
|
|
|
|
|
|
|
|
|
1223
|
|
|
|
|
|
|
} grep s/^_/, keys %main:: ; |
|
1224
|
|
|
|
|
|
|
|
|
1225
|
|
|
|
|
|
|
# |
|
1226
|
|
|
|
|
|
|
# Create a list box with all of our files |
|
1227
|
|
|
|
|
|
|
# to select from |
|
1228
|
|
|
|
|
|
|
# |
|
1229
|
|
|
|
|
|
|
$topLevel = $self->{main_window}->Toplevel(-title => "File Select", -overanchor => 'cursor') ; |
|
1230
|
|
|
|
|
|
|
|
|
1231
|
|
|
|
|
|
|
$listBox = $topLevel->Scrolled('Listbox', |
|
1232
|
|
|
|
|
|
|
@Devel::ptkdb::scrollbar_cfg, |
|
1233
|
|
|
|
|
|
|
@Devel::ptkdb::expression_text_font, |
|
1234
|
|
|
|
|
|
|
-width => 30)->pack(-side => 'top', -fill => 'both', -expand => 1) ; |
|
1235
|
|
|
|
|
|
|
|
|
1236
|
|
|
|
|
|
|
|
|
1237
|
|
|
|
|
|
|
# Bind a double click on the mouse button to the same action |
|
1238
|
|
|
|
|
|
|
# as pressing the Okay button |
|
1239
|
|
|
|
|
|
|
|
|
1240
|
|
|
|
|
|
|
$listBox->bind('' => $chooseSub) ; |
|
1241
|
|
|
|
|
|
|
|
|
1242
|
|
|
|
|
|
|
$listBox->insert('end', @fList) ; |
|
1243
|
|
|
|
|
|
|
|
|
1244
|
|
|
|
|
|
|
$topLevel->Button( -text => "Okay", -command => $chooseSub, @Devel::ptkdb::button_font, |
|
1245
|
|
|
|
|
|
|
)->pack(-side => 'left', -fill => 'both', -expand => 1) ; |
|
1246
|
|
|
|
|
|
|
|
|
1247
|
|
|
|
|
|
|
$topLevel->Button( -text => "Cancel", @Devel::ptkdb::button_font, |
|
1248
|
|
|
|
|
|
|
-command => sub { destroy $topLevel ; } )->pack(-side => 'left', -fill => 'both', -expand => 1) ; |
|
1249
|
|
|
|
|
|
|
} # end of DoOpen |
|
1250
|
|
|
|
|
|
|
|
|
1251
|
|
|
|
|
|
|
sub do_tabs { |
|
1252
|
|
|
|
|
|
|
my($tabs_str) ; |
|
1253
|
|
|
|
|
|
|
my($w, $result, $tabs_cfg) ; |
|
1254
|
|
|
|
|
|
|
require Tk::Dialog ; |
|
1255
|
|
|
|
|
|
|
|
|
1256
|
|
|
|
|
|
|
$w = $DB::window->{'main_window'}->DialogBox(-title => "Tabs", -buttons => [qw/Okay Cancel/]) ; |
|
1257
|
|
|
|
|
|
|
|
|
1258
|
|
|
|
|
|
|
$tabs_cfg = $DB::window->{'text'}->cget(-tabs) ; |
|
1259
|
|
|
|
|
|
|
|
|
1260
|
|
|
|
|
|
|
$tabs_str = join " ", @$tabs_cfg if $tabs_cfg ; |
|
1261
|
|
|
|
|
|
|
|
|
1262
|
|
|
|
|
|
|
$w->add('Label', -text => 'Tabs:')->pack(-side => 'left') ; |
|
1263
|
|
|
|
|
|
|
|
|
1264
|
|
|
|
|
|
|
$w->add('Entry', -textvariable => \$tabs_str)->pack(-side => 'left')->selectionRange(0,'end') ; |
|
1265
|
|
|
|
|
|
|
|
|
1266
|
|
|
|
|
|
|
$result = $w->Show() ; |
|
1267
|
|
|
|
|
|
|
|
|
1268
|
|
|
|
|
|
|
return unless $result eq 'Okay' ; |
|
1269
|
|
|
|
|
|
|
|
|
1270
|
|
|
|
|
|
|
$DB::window->{'text'}->configure(-tabs => [ split /\s/, $tabs_str ]) ; |
|
1271
|
|
|
|
|
|
|
} |
|
1272
|
|
|
|
|
|
|
|
|
1273
|
|
|
|
|
|
|
sub close_ptkdb_window { |
|
1274
|
|
|
|
|
|
|
my($self) = @_ ; |
|
1275
|
|
|
|
|
|
|
|
|
1276
|
|
|
|
|
|
|
$DB::window->{'event'} = 'run' ; |
|
1277
|
|
|
|
|
|
|
$self->{current_file} = "" ; # force a file reset |
|
1278
|
|
|
|
|
|
|
$self->{'main_window'}->destroy ; |
|
1279
|
|
|
|
|
|
|
$self->{'main_window'} = undef ; |
|
1280
|
|
|
|
|
|
|
} |
|
1281
|
|
|
|
|
|
|
|
|
1282
|
|
|
|
|
|
|
sub setup_menu_bar { |
|
1283
|
|
|
|
|
|
|
my ($self) = @_ ; |
|
1284
|
|
|
|
|
|
|
my $mw = $self->{main_window} ; |
|
1285
|
|
|
|
|
|
|
my ($mb, $items) ; |
|
1286
|
|
|
|
|
|
|
|
|
1287
|
|
|
|
|
|
|
# |
|
1288
|
|
|
|
|
|
|
# We have menu items/features that are not available if the Data::DataDumper module |
|
1289
|
|
|
|
|
|
|
# isn't present. For any feature that requires it we add this option list. |
|
1290
|
|
|
|
|
|
|
# |
|
1291
|
|
|
|
|
|
|
my @dataDumperEnableOpt = ( state => 'disabled' ) unless $Devel::ptkdb::DataDumperAvailable ; |
|
1292
|
|
|
|
|
|
|
|
|
1293
|
|
|
|
|
|
|
|
|
1294
|
|
|
|
|
|
|
$self->{menu_bar} = $mw->Frame(-relief => 'raised', -borderwidth => '1')->pack(-side => 'top', -fill => 'x') ; |
|
1295
|
|
|
|
|
|
|
|
|
1296
|
|
|
|
|
|
|
$mb = $self->{menu_bar} ; |
|
1297
|
|
|
|
|
|
|
|
|
1298
|
|
|
|
|
|
|
# file menu in menu bar |
|
1299
|
|
|
|
|
|
|
|
|
1300
|
|
|
|
|
|
|
$items = [ [ 'command' => 'About...', -command => sub { $self->DoAbout() ; } ], |
|
1301
|
|
|
|
|
|
|
[ 'command' => 'Bug Report...', -command => \&DoBugReport ], |
|
1302
|
|
|
|
|
|
|
"-", |
|
1303
|
|
|
|
|
|
|
|
|
1304
|
|
|
|
|
|
|
[ 'command' => 'Open', -accelerator => 'Alt+O', |
|
1305
|
|
|
|
|
|
|
-underline => 0, |
|
1306
|
|
|
|
|
|
|
-command => sub { $self->DoOpen() ; } ], |
|
1307
|
|
|
|
|
|
|
|
|
1308
|
|
|
|
|
|
|
[ 'command' => 'Save Config...', |
|
1309
|
|
|
|
|
|
|
-underline => 0, |
|
1310
|
|
|
|
|
|
|
-command => \&DB::SaveState, |
|
1311
|
|
|
|
|
|
|
@dataDumperEnableOpt ], |
|
1312
|
|
|
|
|
|
|
|
|
1313
|
|
|
|
|
|
|
[ 'command' => 'Restore Config...', |
|
1314
|
|
|
|
|
|
|
-underline => 0, |
|
1315
|
|
|
|
|
|
|
-command => \&DB::RestoreState, |
|
1316
|
|
|
|
|
|
|
@dataDumperEnableOpt ], |
|
1317
|
|
|
|
|
|
|
|
|
1318
|
|
|
|
|
|
|
[ 'command' => 'Goto Line...', |
|
1319
|
|
|
|
|
|
|
-underline => 0, |
|
1320
|
|
|
|
|
|
|
-accelerator => 'Alt-g', |
|
1321
|
|
|
|
|
|
|
-command => sub { $self->GotoLine() ; }, |
|
1322
|
|
|
|
|
|
|
@dataDumperEnableOpt ] , |
|
1323
|
|
|
|
|
|
|
|
|
1324
|
|
|
|
|
|
|
[ 'command' => 'Find Text...', |
|
1325
|
|
|
|
|
|
|
-accelerator => 'Ctrl-f', |
|
1326
|
|
|
|
|
|
|
-underline => 0, |
|
1327
|
|
|
|
|
|
|
-command => sub { $self->FindText() ; } ], |
|
1328
|
|
|
|
|
|
|
|
|
1329
|
|
|
|
|
|
|
[ 'command' => "Tabs...", -command => \&do_tabs ], |
|
1330
|
|
|
|
|
|
|
|
|
1331
|
|
|
|
|
|
|
"-", |
|
1332
|
|
|
|
|
|
|
|
|
1333
|
|
|
|
|
|
|
[ 'command' => 'Close Window and Run', -accelerator => 'Alt+W', |
|
1334
|
|
|
|
|
|
|
-underline => 6, -command => sub { $self->close_ptkdb_window ; } ], |
|
1335
|
|
|
|
|
|
|
|
|
1336
|
|
|
|
|
|
|
[ 'command' => 'Quit...', -accelerator => 'Alt+Q', |
|
1337
|
|
|
|
|
|
|
-underline => 0, |
|
1338
|
|
|
|
|
|
|
-command => sub { $self->DoQuit } ] |
|
1339
|
|
|
|
|
|
|
] ; |
|
1340
|
|
|
|
|
|
|
|
|
1341
|
|
|
|
|
|
|
|
|
1342
|
|
|
|
|
|
|
$mw->bind('' => sub { $self->GotoLine() ; }) ; |
|
1343
|
|
|
|
|
|
|
$mw->bind('' => sub { $self->FindText() ; }) ; |
|
1344
|
|
|
|
|
|
|
$mw->bind('' => \&Devel::ptkdb::DoRestart) ; |
|
1345
|
|
|
|
|
|
|
$mw->bind('' => sub { $self->{'event'} = 'quit' } ) ; |
|
1346
|
|
|
|
|
|
|
$mw->bind('' => sub { $self->close_ptkdb_window ; }) ; |
|
1347
|
|
|
|
|
|
|
|
|
1348
|
|
|
|
|
|
|
$self->{file_menu_button} = $mb->Menubutton(-text => 'File', |
|
1349
|
|
|
|
|
|
|
-underline => 0, |
|
1350
|
|
|
|
|
|
|
-menuitems => $items |
|
1351
|
|
|
|
|
|
|
)->pack(-side =>, 'left', |
|
1352
|
|
|
|
|
|
|
-anchor => 'nw', |
|
1353
|
|
|
|
|
|
|
-padx => 2) ; |
|
1354
|
|
|
|
|
|
|
|
|
1355
|
|
|
|
|
|
|
# Control Menu |
|
1356
|
|
|
|
|
|
|
|
|
1357
|
|
|
|
|
|
|
my $runSub = sub { $DB::step_over_depth = -1 ; $self->{'event'} = 'run' } ; |
|
1358
|
|
|
|
|
|
|
|
|
1359
|
|
|
|
|
|
|
my $runToSub = sub { $DB::window->{'event'} = 'run' if $DB::window->SetBreakPoint(1) ; } ; |
|
1360
|
|
|
|
|
|
|
|
|
1361
|
|
|
|
|
|
|
my $stepOverSub = sub { &DB::SetStepOverBreakPoint(0) ; |
|
1362
|
|
|
|
|
|
|
$DB::single = 1 ; |
|
1363
|
|
|
|
|
|
|
$DB::window->{'event'} = 'step' ; |
|
1364
|
|
|
|
|
|
|
} ; |
|
1365
|
|
|
|
|
|
|
|
|
1366
|
|
|
|
|
|
|
|
|
1367
|
|
|
|
|
|
|
my $stepInSub = sub { |
|
1368
|
|
|
|
|
|
|
$DB::step_over_depth = -1 ; |
|
1369
|
|
|
|
|
|
|
$DB::single = 1 ; |
|
1370
|
|
|
|
|
|
|
$DB::window->{'event'} = 'step' ; } ; |
|
1371
|
|
|
|
|
|
|
|
|
1372
|
|
|
|
|
|
|
|
|
1373
|
|
|
|
|
|
|
my $returnSub = sub { |
|
1374
|
|
|
|
|
|
|
&DB::SetStepOverBreakPoint(-1) ; |
|
1375
|
|
|
|
|
|
|
$self->{'event'} = 'run' ; |
|
1376
|
|
|
|
|
|
|
} ; |
|
1377
|
|
|
|
|
|
|
|
|
1378
|
|
|
|
|
|
|
|
|
1379
|
|
|
|
|
|
|
$items = [ [ 'command' => 'Run', -accelerator => 'Alt+r', -underline => 0, -command => $runSub ], |
|
1380
|
|
|
|
|
|
|
[ 'command' => 'Run To Here', -accelerator => 'Alt+t', -underline => 5, -command => $runToSub ], |
|
1381
|
|
|
|
|
|
|
'-', |
|
1382
|
|
|
|
|
|
|
[ 'command' => 'Set Breakpoint', -underline => 4, -command => sub { $self->SetBreakPoint ; }, -accelerator => 'Ctrl-b' ], |
|
1383
|
|
|
|
|
|
|
[ 'command' => 'Clear Breakpoint', -command => sub { $self->UnsetBreakPoint } ], |
|
1384
|
|
|
|
|
|
|
[ 'command' => 'Clear All Breakpoints', -underline => 6, -command => sub { |
|
1385
|
|
|
|
|
|
|
$DB::window->removeAllBreakpoints($DB::window->{current_file}) ; |
|
1386
|
|
|
|
|
|
|
&DB::clearalldblines() ; |
|
1387
|
|
|
|
|
|
|
} ], |
|
1388
|
|
|
|
|
|
|
'-', |
|
1389
|
|
|
|
|
|
|
[ 'command' => 'Step Over', -accelerator => 'Alt+N', -underline => 0, -command => $stepOverSub ], |
|
1390
|
|
|
|
|
|
|
[ 'command' => 'Step In', -accelerator => 'Alt+S', -underline => 5, -command => $stepInSub ], |
|
1391
|
|
|
|
|
|
|
[ 'command' => 'Return', -accelerator => 'Alt+U', -underline => 3, -command => $returnSub ], |
|
1392
|
|
|
|
|
|
|
'-', |
|
1393
|
|
|
|
|
|
|
[ 'command' => 'Restart...', -accelerator => 'Ctrl-r', -underline => 0, -command => \&Devel::ptkdb::DoRestart ], |
|
1394
|
|
|
|
|
|
|
'-', |
|
1395
|
|
|
|
|
|
|
[ 'checkbutton' => 'Stop On Warning', -variable => \$DB::ptkdb::stop_on_warning, -command => \&set_stop_on_warning ] |
|
1396
|
|
|
|
|
|
|
|
|
1397
|
|
|
|
|
|
|
|
|
1398
|
|
|
|
|
|
|
] ; # end of control menu items |
|
1399
|
|
|
|
|
|
|
|
|
1400
|
|
|
|
|
|
|
|
|
1401
|
|
|
|
|
|
|
$self->{control_menu_button} = $mb->Menubutton(-text => 'Control', |
|
1402
|
|
|
|
|
|
|
-underline => 0, |
|
1403
|
|
|
|
|
|
|
-menuitems => $items, |
|
1404
|
|
|
|
|
|
|
)->pack(-side =>, 'left', |
|
1405
|
|
|
|
|
|
|
-padx => 2) ; |
|
1406
|
|
|
|
|
|
|
|
|
1407
|
|
|
|
|
|
|
|
|
1408
|
|
|
|
|
|
|
$mw->bind('' => $runSub) ; |
|
1409
|
|
|
|
|
|
|
$mw->bind('', $runToSub) ; |
|
1410
|
|
|
|
|
|
|
$mw->bind('', sub { $self->SetBreakPoint ; }) ; |
|
1411
|
|
|
|
|
|
|
|
|
1412
|
|
|
|
|
|
|
for( @Devel::ptkdb::step_over_keys ) { |
|
1413
|
|
|
|
|
|
|
$mw->bind($_ => $stepOverSub ); |
|
1414
|
|
|
|
|
|
|
} |
|
1415
|
|
|
|
|
|
|
|
|
1416
|
|
|
|
|
|
|
for( @Devel::ptkdb::step_in_keys ) { |
|
1417
|
|
|
|
|
|
|
$mw->bind($_ => $stepInSub ); |
|
1418
|
|
|
|
|
|
|
} |
|
1419
|
|
|
|
|
|
|
|
|
1420
|
|
|
|
|
|
|
for( @Devel::ptkdb::return_keys ) { |
|
1421
|
|
|
|
|
|
|
$mw->bind($_ => $returnSub ); |
|
1422
|
|
|
|
|
|
|
} |
|
1423
|
|
|
|
|
|
|
|
|
1424
|
|
|
|
|
|
|
# Data Menu |
|
1425
|
|
|
|
|
|
|
|
|
1426
|
|
|
|
|
|
|
$items = [ [ 'command' => 'Enter Expression', -accelerator => 'Alt+E', -command => sub { $self->EnterExpr() } ], |
|
1427
|
|
|
|
|
|
|
[ 'command' => 'Delete Expression', -accelerator => 'Ctrl+D', -command => sub { $self->deleteExpr() } ], |
|
1428
|
|
|
|
|
|
|
[ 'command' => 'Delete All Expressions', -command => sub { |
|
1429
|
|
|
|
|
|
|
$self->deleteAllExprs() ; |
|
1430
|
|
|
|
|
|
|
$self->{'expr_list'} = [] ; # clears list by dropping ref to it, replacing it with a new one |
|
1431
|
|
|
|
|
|
|
} ], |
|
1432
|
|
|
|
|
|
|
'-', |
|
1433
|
|
|
|
|
|
|
[ 'command' => 'Expression Eval Window...', -accelerator => 'F8', -command => sub { $self->setupEvalWindow() ; } ], |
|
1434
|
|
|
|
|
|
|
[ 'checkbutton' => "Use DataDumper for Eval Window?", -variable => \$Devel::ptkdb::useDataDumperForEval, @dataDumperEnableOpt ] |
|
1435
|
|
|
|
|
|
|
] ; |
|
1436
|
|
|
|
|
|
|
|
|
1437
|
|
|
|
|
|
|
|
|
1438
|
|
|
|
|
|
|
$self->{data_menu_button} = $mb->Menubutton(-text => 'Data', -menuitems => $items, |
|
1439
|
|
|
|
|
|
|
-underline => 0, |
|
1440
|
|
|
|
|
|
|
)->pack(-side => 'left', |
|
1441
|
|
|
|
|
|
|
-padx => 2) ; |
|
1442
|
|
|
|
|
|
|
|
|
1443
|
|
|
|
|
|
|
$mw->bind('' => sub { $self->EnterExpr() } ) ; |
|
1444
|
|
|
|
|
|
|
$mw->bind('' => sub { $self->deleteExpr() } ); |
|
1445
|
|
|
|
|
|
|
$mw->bind('', sub { $self->setupEvalWindow() ; }) ; |
|
1446
|
|
|
|
|
|
|
# |
|
1447
|
|
|
|
|
|
|
# Stack menu |
|
1448
|
|
|
|
|
|
|
# |
|
1449
|
|
|
|
|
|
|
$self->{stack_menu} = $mb->Menubutton(-text => 'Stack', |
|
1450
|
|
|
|
|
|
|
-underline => 2, |
|
1451
|
|
|
|
|
|
|
)->pack(-side => 'left', |
|
1452
|
|
|
|
|
|
|
-padx => 2) ; |
|
1453
|
|
|
|
|
|
|
|
|
1454
|
|
|
|
|
|
|
# |
|
1455
|
|
|
|
|
|
|
# Bookmarks menu |
|
1456
|
|
|
|
|
|
|
# |
|
1457
|
|
|
|
|
|
|
$self->{bookmarks_menu} = $mb->Menubutton(-text => 'Bookmarks', |
|
1458
|
|
|
|
|
|
|
-underline => 0, |
|
1459
|
|
|
|
|
|
|
@dataDumperEnableOpt |
|
1460
|
|
|
|
|
|
|
)->pack(-side => 'left', |
|
1461
|
|
|
|
|
|
|
-padx => 2) ; |
|
1462
|
|
|
|
|
|
|
$self->setup_bookmarks_menu() ; |
|
1463
|
|
|
|
|
|
|
|
|
1464
|
|
|
|
|
|
|
# |
|
1465
|
|
|
|
|
|
|
# Windows Menu |
|
1466
|
|
|
|
|
|
|
# |
|
1467
|
|
|
|
|
|
|
my($bsub) = sub { $self->{'text'}->focus() } ; |
|
1468
|
|
|
|
|
|
|
my($csub) = sub { $self->{'quick_entry'}->focus() } ; |
|
1469
|
|
|
|
|
|
|
my($dsub) = sub { $self->{'entry'}->focus() } ; |
|
1470
|
|
|
|
|
|
|
|
|
1471
|
|
|
|
|
|
|
$items = [ [ 'command' => 'Code Pane', -accelerator => 'Alt+0', -command => $bsub ], |
|
1472
|
|
|
|
|
|
|
[ 'command' => 'Quick Entry', -accelerator => 'F9', -command => $csub ], |
|
1473
|
|
|
|
|
|
|
[ 'command' => 'Expr Entry', -accelerator => 'F11', -command => $dsub ] |
|
1474
|
|
|
|
|
|
|
] ; |
|
1475
|
|
|
|
|
|
|
|
|
1476
|
|
|
|
|
|
|
$mb->Menubutton(-text => 'Windows', -menuitems => $items |
|
1477
|
|
|
|
|
|
|
)->pack(-side => 'left', |
|
1478
|
|
|
|
|
|
|
-padx => 2) ; |
|
1479
|
|
|
|
|
|
|
|
|
1480
|
|
|
|
|
|
|
$mw->bind('', $bsub) ; |
|
1481
|
|
|
|
|
|
|
$mw->bind('', $csub) ; |
|
1482
|
|
|
|
|
|
|
$mw->bind('', $dsub) ; |
|
1483
|
|
|
|
|
|
|
|
|
1484
|
|
|
|
|
|
|
# |
|
1485
|
|
|
|
|
|
|
# Bar for some popular controls |
|
1486
|
|
|
|
|
|
|
# |
|
1487
|
|
|
|
|
|
|
|
|
1488
|
|
|
|
|
|
|
$self->{button_bar} = $mw->Frame()->pack(-side => 'top') ; |
|
1489
|
|
|
|
|
|
|
|
|
1490
|
|
|
|
|
|
|
$self->{stepin_button} = $self->{button_bar}->Button(-text, => "Step In", @Devel::ptkdb::button_font, |
|
1491
|
|
|
|
|
|
|
-command => $stepInSub) ; |
|
1492
|
|
|
|
|
|
|
$self->{stepin_button}->pack(-side => 'left') ; |
|
1493
|
|
|
|
|
|
|
|
|
1494
|
|
|
|
|
|
|
$self->{stepover_button} = $self->{button_bar}->Button(-text, => "Step Over", @Devel::ptkdb::button_font, |
|
1495
|
|
|
|
|
|
|
-command => $stepOverSub) ; |
|
1496
|
|
|
|
|
|
|
$self->{stepover_button}->pack(-side => 'left') ; |
|
1497
|
|
|
|
|
|
|
|
|
1498
|
|
|
|
|
|
|
$self->{return_button} = $self->{button_bar}->Button(-text, => "Return", @Devel::ptkdb::button_font, |
|
1499
|
|
|
|
|
|
|
-command => $returnSub) ; |
|
1500
|
|
|
|
|
|
|
$self->{return_button}->pack(-side => 'left') ; |
|
1501
|
|
|
|
|
|
|
|
|
1502
|
|
|
|
|
|
|
$self->{run_button} = $self->{button_bar}->Button(-background => 'green', -text, => "Run", @Devel::ptkdb::button_font, |
|
1503
|
|
|
|
|
|
|
-command => $runSub) ; |
|
1504
|
|
|
|
|
|
|
$self->{run_button}->pack(-side => 'left') ; |
|
1505
|
|
|
|
|
|
|
|
|
1506
|
|
|
|
|
|
|
$self->{run_to_button} = $self->{button_bar}->Button(-text, => "Run To", @Devel::ptkdb::button_font, |
|
1507
|
|
|
|
|
|
|
-command => $runToSub) ; |
|
1508
|
|
|
|
|
|
|
$self->{run_to_button}->pack(-side => 'left') ; |
|
1509
|
|
|
|
|
|
|
|
|
1510
|
|
|
|
|
|
|
$self->{breakpt_button} = $self->{button_bar}->Button(-text, => "Break", @Devel::ptkdb::button_font, |
|
1511
|
|
|
|
|
|
|
-command => sub { $self->SetBreakPoint ; } ) ; |
|
1512
|
|
|
|
|
|
|
$self->{breakpt_button}->pack(-side => 'left') ; |
|
1513
|
|
|
|
|
|
|
|
|
1514
|
|
|
|
|
|
|
push @{$self->{DisableOnLeave}}, @$self{'stepin_button', 'stepover_button', 'return_button', 'run_button', 'run_to_button', 'breakpt_button'} ; |
|
1515
|
|
|
|
|
|
|
|
|
1516
|
|
|
|
|
|
|
} # end of setup_menu_bar |
|
1517
|
|
|
|
|
|
|
|
|
1518
|
|
|
|
|
|
|
sub edit_bookmarks { |
|
1519
|
|
|
|
|
|
|
my ($self) = @_ ; |
|
1520
|
|
|
|
|
|
|
|
|
1521
|
|
|
|
|
|
|
my ($top) = $self->{main_window}->Toplevel(-title => "Edit Bookmarks") ; |
|
1522
|
|
|
|
|
|
|
|
|
1523
|
|
|
|
|
|
|
my $list = $top->Scrolled('Listbox', -selectmode => 'multiple')->pack(-side => 'top', -fill => 'both', -expand => 1) ; |
|
1524
|
|
|
|
|
|
|
|
|
1525
|
|
|
|
|
|
|
my $deleteSub = sub { |
|
1526
|
|
|
|
|
|
|
my $cnt = 0 ; |
|
1527
|
|
|
|
|
|
|
for( $list->curselection ) { |
|
1528
|
|
|
|
|
|
|
$list->delete($_ - $cnt++) ; |
|
1529
|
|
|
|
|
|
|
} |
|
1530
|
|
|
|
|
|
|
} ; |
|
1531
|
|
|
|
|
|
|
|
|
1532
|
|
|
|
|
|
|
my $okaySub = sub { |
|
1533
|
|
|
|
|
|
|
$self->{'bookmarks'} = [ $list->get(0, 'end') ] ; # replace the bookmarks |
|
1534
|
|
|
|
|
|
|
} ; |
|
1535
|
|
|
|
|
|
|
|
|
1536
|
|
|
|
|
|
|
my $frm = $top->Frame()->pack(-side => 'top', -fill => 'x', -expand => 1 ) ; |
|
1537
|
|
|
|
|
|
|
|
|
1538
|
|
|
|
|
|
|
my $deleteBtn = $frm->Button(-text => 'Delete', -command => $deleteSub)->pack(-side => 'left', -fill => 'x', -expand => 1 ) ; |
|
1539
|
|
|
|
|
|
|
my $cancelBtn = $frm->Button(-text => 'Cancel', -command => sub { destroy $top ; })->pack(-side =>'left', -fill => 'x', -expand => 1 ) ; |
|
1540
|
|
|
|
|
|
|
my $dismissBtn = $frm->Button(-text => 'Okay', -command => $okaySub)->pack(-side => 'left', -fill => 'x', -expand => 1 ) ; |
|
1541
|
|
|
|
|
|
|
|
|
1542
|
|
|
|
|
|
|
$list->insert('end', @{$self->{'bookmarks'}}) ; |
|
1543
|
|
|
|
|
|
|
|
|
1544
|
|
|
|
|
|
|
} # end of edit_bookmarks |
|
1545
|
|
|
|
|
|
|
|
|
1546
|
|
|
|
|
|
|
sub setup_bookmarks_menu { |
|
1547
|
|
|
|
|
|
|
my ($self) = @_ ; |
|
1548
|
|
|
|
|
|
|
|
|
1549
|
|
|
|
|
|
|
# |
|
1550
|
|
|
|
|
|
|
# "Add bookmark" item |
|
1551
|
|
|
|
|
|
|
# |
|
1552
|
|
|
|
|
|
|
my $bkMarkSub = sub { $self->add_bookmark() ; } ; |
|
1553
|
|
|
|
|
|
|
|
|
1554
|
|
|
|
|
|
|
$self->{'bookmarks_menu'}->command(-label => "Add Bookmark", |
|
1555
|
|
|
|
|
|
|
-accelerator => 'Alt+k', |
|
1556
|
|
|
|
|
|
|
-command => $bkMarkSub |
|
1557
|
|
|
|
|
|
|
) ; |
|
1558
|
|
|
|
|
|
|
|
|
1559
|
|
|
|
|
|
|
$self->{'main_window'}->bind('', $bkMarkSub) ; |
|
1560
|
|
|
|
|
|
|
|
|
1561
|
|
|
|
|
|
|
$self->{'bookmarks_menu'}->command(-label => "Edit Bookmarks", |
|
1562
|
|
|
|
|
|
|
-command => sub { $self->edit_bookmarks() } ) ; |
|
1563
|
|
|
|
|
|
|
|
|
1564
|
|
|
|
|
|
|
$self->{'bookmarks_menu'}->separator() ; |
|
1565
|
|
|
|
|
|
|
|
|
1566
|
|
|
|
|
|
|
# |
|
1567
|
|
|
|
|
|
|
# Check to see if there is a bookmarks file |
|
1568
|
|
|
|
|
|
|
# |
|
1569
|
|
|
|
|
|
|
return unless -e $self->{BookMarksPath} && -r $self->{BookMarksPath} ; |
|
1570
|
|
|
|
|
|
|
|
|
1571
|
|
|
|
|
|
|
use vars qw($ptkdb_bookmarks) ; |
|
1572
|
|
|
|
|
|
|
local($ptkdb_bookmarks) ; # ref to hash of bookmark entries |
|
1573
|
|
|
|
|
|
|
|
|
1574
|
|
|
|
|
|
|
do $self->{BookMarksPath} ; # eval the file |
|
1575
|
|
|
|
|
|
|
|
|
1576
|
|
|
|
|
|
|
$self->add_bookmark_items(@$ptkdb_bookmarks) ; |
|
1577
|
|
|
|
|
|
|
|
|
1578
|
|
|
|
|
|
|
} # end of setup_bookmarks_menu |
|
1579
|
|
|
|
|
|
|
|
|
1580
|
|
|
|
|
|
|
# |
|
1581
|
|
|
|
|
|
|
# $item = "$fname:$lineno" |
|
1582
|
|
|
|
|
|
|
# |
|
1583
|
|
|
|
|
|
|
sub add_bookmark_items { |
|
1584
|
|
|
|
|
|
|
my($self, @items) = @_ ; |
|
1585
|
|
|
|
|
|
|
my($menu) = ( $self->{'bookmarks_menu'} ) ; |
|
1586
|
|
|
|
|
|
|
|
|
1587
|
|
|
|
|
|
|
$self->{'bookmarks_changed'} = 1 ; |
|
1588
|
|
|
|
|
|
|
|
|
1589
|
|
|
|
|
|
|
for( @items ) { |
|
1590
|
|
|
|
|
|
|
my $item = $_ ; |
|
1591
|
|
|
|
|
|
|
$menu->command( -label => $_, |
|
1592
|
|
|
|
|
|
|
-command => sub { $self->bookmark_cmd($item) }) ; |
|
1593
|
|
|
|
|
|
|
push @{$self->{'bookmarks'}}, $item ; |
|
1594
|
|
|
|
|
|
|
} |
|
1595
|
|
|
|
|
|
|
} # end of add_bookmark_item |
|
1596
|
|
|
|
|
|
|
|
|
1597
|
|
|
|
|
|
|
# |
|
1598
|
|
|
|
|
|
|
# Invoked from the "Add Bookmark" command |
|
1599
|
|
|
|
|
|
|
# |
|
1600
|
|
|
|
|
|
|
sub add_bookmark { |
|
1601
|
|
|
|
|
|
|
my($self) = @_ ; |
|
1602
|
|
|
|
|
|
|
|
|
1603
|
|
|
|
|
|
|
my $line = $self->get_lineno() ; |
|
1604
|
|
|
|
|
|
|
my $fname = $self->{'current_file'} ; |
|
1605
|
|
|
|
|
|
|
$self->add_bookmark_items("$fname:$line") ; |
|
1606
|
|
|
|
|
|
|
|
|
1607
|
|
|
|
|
|
|
} # end of add_bookmark |
|
1608
|
|
|
|
|
|
|
|
|
1609
|
|
|
|
|
|
|
# |
|
1610
|
|
|
|
|
|
|
# Command executed when someone selects |
|
1611
|
|
|
|
|
|
|
# a bookmark |
|
1612
|
|
|
|
|
|
|
# |
|
1613
|
|
|
|
|
|
|
sub bookmark_cmd { |
|
1614
|
|
|
|
|
|
|
my ($self, $item) = @_ ; |
|
1615
|
|
|
|
|
|
|
|
|
1616
|
|
|
|
|
|
|
$item =~ /(.*):([0-9]+)$/ ; |
|
1617
|
|
|
|
|
|
|
|
|
1618
|
|
|
|
|
|
|
$self->set_file($1,$2) ; |
|
1619
|
|
|
|
|
|
|
|
|
1620
|
|
|
|
|
|
|
} # end of bookmark_cmd |
|
1621
|
|
|
|
|
|
|
|
|
1622
|
|
|
|
|
|
|
sub save_bookmarks { |
|
1623
|
|
|
|
|
|
|
my($self, $pathName) = @_ ; |
|
1624
|
|
|
|
|
|
|
|
|
1625
|
|
|
|
|
|
|
return unless $Devel::ptkdb::DataDumperAvailable ; # we can't save without the data dumper |
|
1626
|
|
|
|
|
|
|
local(*F) ; |
|
1627
|
|
|
|
|
|
|
|
|
1628
|
|
|
|
|
|
|
eval { |
|
1629
|
|
|
|
|
|
|
open F, ">$pathName" || die "open failed" ; |
|
1630
|
|
|
|
|
|
|
my $d = Data::Dumper->new([ $self->{'bookmarks'} ], |
|
1631
|
|
|
|
|
|
|
[ 'ptkdb_bookmarks' ]) ; |
|
1632
|
|
|
|
|
|
|
|
|
1633
|
|
|
|
|
|
|
$d->Indent(2) ; # make it more editable for people |
|
1634
|
|
|
|
|
|
|
|
|
1635
|
|
|
|
|
|
|
my $str ; |
|
1636
|
|
|
|
|
|
|
if( $d->can('Dumpxs') ) { |
|
1637
|
|
|
|
|
|
|
$str = $d->Dumpxs() ; |
|
1638
|
|
|
|
|
|
|
} |
|
1639
|
|
|
|
|
|
|
else { |
|
1640
|
|
|
|
|
|
|
$str = $d->Dump() ; |
|
1641
|
|
|
|
|
|
|
} |
|
1642
|
|
|
|
|
|
|
|
|
1643
|
|
|
|
|
|
|
print F $str || die "outputing bookmarks failed" ; |
|
1644
|
|
|
|
|
|
|
close(F) ; |
|
1645
|
|
|
|
|
|
|
} ; |
|
1646
|
|
|
|
|
|
|
|
|
1647
|
|
|
|
|
|
|
if( $@ ) { |
|
1648
|
|
|
|
|
|
|
$self->DoAlert("Couldn't save bookmarks file $@") ; |
|
1649
|
|
|
|
|
|
|
return ; |
|
1650
|
|
|
|
|
|
|
} |
|
1651
|
|
|
|
|
|
|
|
|
1652
|
|
|
|
|
|
|
} # end of save_bookmarks |
|
1653
|
|
|
|
|
|
|
|
|
1654
|
|
|
|
|
|
|
# |
|
1655
|
|
|
|
|
|
|
# This is our callback from a double click in our |
|
1656
|
|
|
|
|
|
|
# HList. A click in an expanded item will delete |
|
1657
|
|
|
|
|
|
|
# the children beneath it, and the next time it |
|
1658
|
|
|
|
|
|
|
# updates, it will only update that entry to that |
|
1659
|
|
|
|
|
|
|
# depth. If an item is 'unexpanded' such as |
|
1660
|
|
|
|
|
|
|
# a hash or a list, it will expand it one more |
|
1661
|
|
|
|
|
|
|
# level. How much further an item is expanded is |
|
1662
|
|
|
|
|
|
|
# controled by package variable $Devel::ptkdb::add_expr_depth |
|
1663
|
|
|
|
|
|
|
# |
|
1664
|
|
|
|
|
|
|
sub expr_expand { |
|
1665
|
|
|
|
|
|
|
my ($path) = @_ ; |
|
1666
|
|
|
|
|
|
|
my $hl = $DB::window->{'data_list'} ; |
|
1667
|
|
|
|
|
|
|
my ($parent, $root, $index, @children, $depth) ; |
|
1668
|
|
|
|
|
|
|
|
|
1669
|
|
|
|
|
|
|
$parent = $path ; |
|
1670
|
|
|
|
|
|
|
$root = $path ; |
|
1671
|
|
|
|
|
|
|
$depth = 0 ; |
|
1672
|
|
|
|
|
|
|
|
|
1673
|
|
|
|
|
|
|
for( $root = $path ; defined $parent && $parent ne "" ; $parent = $hl->infoParent($root) ) { |
|
1674
|
|
|
|
|
|
|
$root = $parent ; |
|
1675
|
|
|
|
|
|
|
$depth += 1 ; |
|
1676
|
|
|
|
|
|
|
} #end of root search |
|
1677
|
|
|
|
|
|
|
|
|
1678
|
|
|
|
|
|
|
# |
|
1679
|
|
|
|
|
|
|
# Determine the index of the root of our expression |
|
1680
|
|
|
|
|
|
|
# |
|
1681
|
|
|
|
|
|
|
$index = 0 ; |
|
1682
|
|
|
|
|
|
|
for( @{$DB::window->{'expr_list'}} ) { |
|
1683
|
|
|
|
|
|
|
last if $_->{'expr'} eq $root ; |
|
1684
|
|
|
|
|
|
|
$index += 1 ; |
|
1685
|
|
|
|
|
|
|
} |
|
1686
|
|
|
|
|
|
|
|
|
1687
|
|
|
|
|
|
|
# |
|
1688
|
|
|
|
|
|
|
# if we have children we're going to delete them |
|
1689
|
|
|
|
|
|
|
# |
|
1690
|
|
|
|
|
|
|
|
|
1691
|
|
|
|
|
|
|
@children = $hl->infoChildren($path) ; |
|
1692
|
|
|
|
|
|
|
|
|
1693
|
|
|
|
|
|
|
if( scalar @children > 0 ) { |
|
1694
|
|
|
|
|
|
|
|
|
1695
|
|
|
|
|
|
|
$hl->deleteOffsprings($path) ; |
|
1696
|
|
|
|
|
|
|
|
|
1697
|
|
|
|
|
|
|
$DB::window->{'expr_list'}->[$index]->{'depth'} = $depth - 1 ; # adjust our depth |
|
1698
|
|
|
|
|
|
|
} |
|
1699
|
|
|
|
|
|
|
else { |
|
1700
|
|
|
|
|
|
|
# |
|
1701
|
|
|
|
|
|
|
# Delete the existing tree and insert a new one |
|
1702
|
|
|
|
|
|
|
# |
|
1703
|
|
|
|
|
|
|
$hl->deleteEntry($root) ; |
|
1704
|
|
|
|
|
|
|
$hl->add($root, -at => $index) ; |
|
1705
|
|
|
|
|
|
|
$DB::window->{'expr_list'}->[$index]->{'depth'} += $Devel::ptkdb::add_expr_depth ; |
|
1706
|
|
|
|
|
|
|
# |
|
1707
|
|
|
|
|
|
|
# Force an update on our expressions |
|
1708
|
|
|
|
|
|
|
# |
|
1709
|
|
|
|
|
|
|
$DB::window->{'event'} = 'update' ; |
|
1710
|
|
|
|
|
|
|
} |
|
1711
|
|
|
|
|
|
|
} # end of expr_expand |
|
1712
|
|
|
|
|
|
|
|
|
1713
|
|
|
|
|
|
|
sub line_number_from_coord { |
|
1714
|
|
|
|
|
|
|
my($txtWidget, $coord) = @_ ; |
|
1715
|
|
|
|
|
|
|
my($index) ; |
|
1716
|
|
|
|
|
|
|
|
|
1717
|
|
|
|
|
|
|
$index = $txtWidget->index($coord) ; |
|
1718
|
|
|
|
|
|
|
|
|
1719
|
|
|
|
|
|
|
# index is in the format of lineno.column |
|
1720
|
|
|
|
|
|
|
|
|
1721
|
|
|
|
|
|
|
$index =~ /([0-9]*)\.([0-9]*)/o ; |
|
1722
|
|
|
|
|
|
|
|
|
1723
|
|
|
|
|
|
|
# |
|
1724
|
|
|
|
|
|
|
# return a list of (col, line). Why |
|
1725
|
|
|
|
|
|
|
# backwards? |
|
1726
|
|
|
|
|
|
|
# |
|
1727
|
|
|
|
|
|
|
|
|
1728
|
|
|
|
|
|
|
return ($2 ,$1) ; |
|
1729
|
|
|
|
|
|
|
|
|
1730
|
|
|
|
|
|
|
} # end of line_number_from_coord |
|
1731
|
|
|
|
|
|
|
|
|
1732
|
|
|
|
|
|
|
# |
|
1733
|
|
|
|
|
|
|
# It may seem as if $txtWidget and $self are |
|
1734
|
|
|
|
|
|
|
# erroneously reversed, but this is a result |
|
1735
|
|
|
|
|
|
|
# of the calling syntax of the text-bind callback. |
|
1736
|
|
|
|
|
|
|
# |
|
1737
|
|
|
|
|
|
|
sub set_breakpoint_tag { |
|
1738
|
|
|
|
|
|
|
my($txtWidget, $self, $coord, $value) = @_ ; |
|
1739
|
|
|
|
|
|
|
my($idx) ; |
|
1740
|
|
|
|
|
|
|
|
|
1741
|
|
|
|
|
|
|
$idx = line_number_from_coord($txtWidget, $coord) ; |
|
1742
|
|
|
|
|
|
|
|
|
1743
|
|
|
|
|
|
|
$self->insertBreakpoint($self->{'current_file'}, $idx, $value) ; |
|
1744
|
|
|
|
|
|
|
|
|
1745
|
|
|
|
|
|
|
} # end of set_breakpoint_tag |
|
1746
|
|
|
|
|
|
|
|
|
1747
|
|
|
|
|
|
|
sub clear_breakpoint_tag { |
|
1748
|
|
|
|
|
|
|
my($txtWidget, $self, $coord) = @_ ; |
|
1749
|
|
|
|
|
|
|
my($idx) ; |
|
1750
|
|
|
|
|
|
|
|
|
1751
|
|
|
|
|
|
|
$idx = line_number_from_coord($txtWidget, $coord) ; |
|
1752
|
|
|
|
|
|
|
|
|
1753
|
|
|
|
|
|
|
$self->removeBreakpoint($self->{'current_file'}, $idx) ; |
|
1754
|
|
|
|
|
|
|
|
|
1755
|
|
|
|
|
|
|
} # end of clear_breakpoint_tag |
|
1756
|
|
|
|
|
|
|
|
|
1757
|
|
|
|
|
|
|
sub change_breakpoint_tag { |
|
1758
|
|
|
|
|
|
|
my($txtWidget, $self, $coord, $value) = @_ ; |
|
1759
|
|
|
|
|
|
|
my($idx, $brkPt, @tagSet) ; |
|
1760
|
|
|
|
|
|
|
|
|
1761
|
|
|
|
|
|
|
$idx = line_number_from_coord($txtWidget, $coord) ; |
|
1762
|
|
|
|
|
|
|
|
|
1763
|
|
|
|
|
|
|
# |
|
1764
|
|
|
|
|
|
|
# Change the value of the breakpoint |
|
1765
|
|
|
|
|
|
|
# |
|
1766
|
|
|
|
|
|
|
@tagSet = ( "$idx.0", "$idx.$Devel::ptkdb::linenumber_length" ) ; |
|
1767
|
|
|
|
|
|
|
|
|
1768
|
|
|
|
|
|
|
$brkPt = &DB::getdbline($self->{'current_file'}, $idx + $self->{'line_offset'}) ; |
|
1769
|
|
|
|
|
|
|
return unless $brkPt ; |
|
1770
|
|
|
|
|
|
|
|
|
1771
|
|
|
|
|
|
|
# |
|
1772
|
|
|
|
|
|
|
# Check the breakpoint tag |
|
1773
|
|
|
|
|
|
|
# |
|
1774
|
|
|
|
|
|
|
|
|
1775
|
|
|
|
|
|
|
if ( $txtWidget ) { |
|
1776
|
|
|
|
|
|
|
$txtWidget->tagRemove('breaksetLine', @tagSet ) ; |
|
1777
|
|
|
|
|
|
|
$txtWidget->tagRemove('breakdisabledLine', @tagSet ) ; |
|
1778
|
|
|
|
|
|
|
} |
|
1779
|
|
|
|
|
|
|
|
|
1780
|
|
|
|
|
|
|
$brkPt->{'value'} = $value ; |
|
1781
|
|
|
|
|
|
|
|
|
1782
|
|
|
|
|
|
|
if ( $txtWidget ) { |
|
1783
|
|
|
|
|
|
|
if ( $brkPt->{'value'} ) { |
|
1784
|
|
|
|
|
|
|
$txtWidget->tagAdd('breaksetLine', @tagSet ) ; |
|
1785
|
|
|
|
|
|
|
} |
|
1786
|
|
|
|
|
|
|
else { |
|
1787
|
|
|
|
|
|
|
$txtWidget->tagAdd('breakdisabledLine', @tagSet ) ; |
|
1788
|
|
|
|
|
|
|
} |
|
1789
|
|
|
|
|
|
|
} |
|
1790
|
|
|
|
|
|
|
|
|
1791
|
|
|
|
|
|
|
} # end of change_breakpoint_tag |
|
1792
|
|
|
|
|
|
|
|
|
1793
|
|
|
|
|
|
|
# |
|
1794
|
|
|
|
|
|
|
# God Forbid anyone comment something complex and tightly optimized. |
|
1795
|
|
|
|
|
|
|
# |
|
1796
|
|
|
|
|
|
|
# We can get a list of the subroutines from the interpreter |
|
1797
|
|
|
|
|
|
|
# by querrying the *DB::sub typeglob: keys %DB::sub |
|
1798
|
|
|
|
|
|
|
# |
|
1799
|
|
|
|
|
|
|
# The list appears broken down by module: |
|
1800
|
|
|
|
|
|
|
# |
|
1801
|
|
|
|
|
|
|
# main::BEGIN |
|
1802
|
|
|
|
|
|
|
# main::mySub |
|
1803
|
|
|
|
|
|
|
# main::otherSub |
|
1804
|
|
|
|
|
|
|
# Tk::Adjuster::Mapped |
|
1805
|
|
|
|
|
|
|
# Tk::Adjuster::Packed |
|
1806
|
|
|
|
|
|
|
# Tk::Button::BEGIN |
|
1807
|
|
|
|
|
|
|
# Tk::Button::Enter |
|
1808
|
|
|
|
|
|
|
# |
|
1809
|
|
|
|
|
|
|
# We would like to break this list down into a heirarchy. |
|
1810
|
|
|
|
|
|
|
# |
|
1811
|
|
|
|
|
|
|
# main Tk |
|
1812
|
|
|
|
|
|
|
# | | | | |
|
1813
|
|
|
|
|
|
|
# BEGIN mySub OtherSub | | |
|
1814
|
|
|
|
|
|
|
# Adjuster Button |
|
1815
|
|
|
|
|
|
|
# | | | | |
|
1816
|
|
|
|
|
|
|
# Mapped Packed BEGIN Enter |
|
1817
|
|
|
|
|
|
|
# |
|
1818
|
|
|
|
|
|
|
# |
|
1819
|
|
|
|
|
|
|
# We translate this list into a heirarchy of hashes(say three times fast). |
|
1820
|
|
|
|
|
|
|
# We take each entry and split it into elements. Each element is a leaf in the tree. |
|
1821
|
|
|
|
|
|
|
# We traverse the tree with the inner for loop. |
|
1822
|
|
|
|
|
|
|
# With each branch we check to see if it already exists or |
|
1823
|
|
|
|
|
|
|
# we create it. When we reach the last element, this becomes our entry. |
|
1824
|
|
|
|
|
|
|
# |
|
1825
|
|
|
|
|
|
|
|
|
1826
|
|
|
|
|
|
|
# |
|
1827
|
|
|
|
|
|
|
# An incoming list is potentially 'large' so we |
|
1828
|
|
|
|
|
|
|
# pass in the ref to it instead. |
|
1829
|
|
|
|
|
|
|
# |
|
1830
|
|
|
|
|
|
|
# New entries can be inserted by providing a $topH |
|
1831
|
|
|
|
|
|
|
# hash ref to an existing tree. |
|
1832
|
|
|
|
|
|
|
# |
|
1833
|
|
|
|
|
|
|
sub tree_split { |
|
1834
|
|
|
|
|
|
|
my ($listRef, $separator, $topH) = @_ ; |
|
1835
|
|
|
|
|
|
|
my ($h, $list_elem) ; |
|
1836
|
|
|
|
|
|
|
|
|
1837
|
|
|
|
|
|
|
$topH = {} unless $topH ; |
|
1838
|
|
|
|
|
|
|
|
|
1839
|
|
|
|
|
|
|
foreach $list_elem ( @$listRef ) { |
|
1840
|
|
|
|
|
|
|
$h = $topH ; |
|
1841
|
|
|
|
|
|
|
for( split /$separator/o, $list_elem ) { # Tk::Adjuster::Mapped -> ( Tk Adjuster Mapped ) |
|
1842
|
|
|
|
|
|
|
$h->{$_} or $h->{$_} = {} ; # either we have an entry for this OR we create one |
|
1843
|
|
|
|
|
|
|
$h = $h->{$_} ; |
|
1844
|
|
|
|
|
|
|
} |
|
1845
|
|
|
|
|
|
|
@$h{'name', 'path'} = ($_, $list_elem) ; # the last leaf is our entry |
|
1846
|
|
|
|
|
|
|
} # end of tree_split loop |
|
1847
|
|
|
|
|
|
|
|
|
1848
|
|
|
|
|
|
|
return $topH ; |
|
1849
|
|
|
|
|
|
|
|
|
1850
|
|
|
|
|
|
|
} # end of tree_split |
|
1851
|
|
|
|
|
|
|
|
|
1852
|
|
|
|
|
|
|
# |
|
1853
|
|
|
|
|
|
|
# callback executed when someone double clicks |
|
1854
|
|
|
|
|
|
|
# an entry in the 'Subs' Tk::Notebook page. |
|
1855
|
|
|
|
|
|
|
# |
|
1856
|
|
|
|
|
|
|
sub sub_list_cmd { |
|
1857
|
|
|
|
|
|
|
my ($self, $path) = @_ ; |
|
1858
|
|
|
|
|
|
|
my ($h) ; |
|
1859
|
|
|
|
|
|
|
my $sub_list = $self->{'sub_list'} ; |
|
1860
|
|
|
|
|
|
|
|
|
1861
|
|
|
|
|
|
|
if ( $sub_list->info('children', $path) ) { |
|
1862
|
|
|
|
|
|
|
# |
|
1863
|
|
|
|
|
|
|
# Delete the children |
|
1864
|
|
|
|
|
|
|
# |
|
1865
|
|
|
|
|
|
|
$sub_list->deleteOffsprings($path) ; |
|
1866
|
|
|
|
|
|
|
return ; |
|
1867
|
|
|
|
|
|
|
} |
|
1868
|
|
|
|
|
|
|
|
|
1869
|
|
|
|
|
|
|
# |
|
1870
|
|
|
|
|
|
|
# split the path up into elements |
|
1871
|
|
|
|
|
|
|
# end descend through the tree. |
|
1872
|
|
|
|
|
|
|
# |
|
1873
|
|
|
|
|
|
|
$h = $Devel::ptkdb::subs_tree ; |
|
1874
|
|
|
|
|
|
|
for ( split /\./o, $path ) { |
|
1875
|
|
|
|
|
|
|
$h = $h->{$_} ; # next level down |
|
1876
|
|
|
|
|
|
|
} |
|
1877
|
|
|
|
|
|
|
|
|
1878
|
|
|
|
|
|
|
# |
|
1879
|
|
|
|
|
|
|
# if we don't have a 'name' entry we |
|
1880
|
|
|
|
|
|
|
# still have levels to decend through. |
|
1881
|
|
|
|
|
|
|
# |
|
1882
|
|
|
|
|
|
|
if ( !exists $h->{'name'} ) { |
|
1883
|
|
|
|
|
|
|
# |
|
1884
|
|
|
|
|
|
|
# Add the next level paths |
|
1885
|
|
|
|
|
|
|
# |
|
1886
|
|
|
|
|
|
|
for ( sort keys %$h ) { |
|
1887
|
|
|
|
|
|
|
|
|
1888
|
|
|
|
|
|
|
if ( exists $h->{$_}->{'path'} ) { |
|
1889
|
|
|
|
|
|
|
$sub_list->add($path . '.' . $_, -text => $h->{$_}->{'path'}) ; |
|
1890
|
|
|
|
|
|
|
} |
|
1891
|
|
|
|
|
|
|
else { |
|
1892
|
|
|
|
|
|
|
$sub_list->add($path . '.' . $_, -text => $_) ; |
|
1893
|
|
|
|
|
|
|
} |
|
1894
|
|
|
|
|
|
|
} |
|
1895
|
|
|
|
|
|
|
return ; |
|
1896
|
|
|
|
|
|
|
} |
|
1897
|
|
|
|
|
|
|
|
|
1898
|
|
|
|
|
|
|
$DB::sub{$h->{'path'}} =~ /(.*):([0-9]+)-[0-9]+$/o ; # file name will be in $1, line number will be in $2 */ |
|
1899
|
|
|
|
|
|
|
|
|
1900
|
|
|
|
|
|
|
$self->set_file($1, $2) ; |
|
1901
|
|
|
|
|
|
|
|
|
1902
|
|
|
|
|
|
|
} # end of sub_list_cmd |
|
1903
|
|
|
|
|
|
|
|
|
1904
|
|
|
|
|
|
|
sub fill_subs_page { |
|
1905
|
|
|
|
|
|
|
my($self) = @_ ; |
|
1906
|
|
|
|
|
|
|
|
|
1907
|
|
|
|
|
|
|
$self->{'sub_list'}->delete('all') ; # clear existing entries |
|
1908
|
|
|
|
|
|
|
|
|
1909
|
|
|
|
|
|
|
my @list = keys %DB::sub ; |
|
1910
|
|
|
|
|
|
|
|
|
1911
|
|
|
|
|
|
|
$Devel::ptkdb::subs_tree = tree_split(\@list, "::") ; |
|
1912
|
|
|
|
|
|
|
|
|
1913
|
|
|
|
|
|
|
# setup to level of list |
|
1914
|
|
|
|
|
|
|
|
|
1915
|
|
|
|
|
|
|
for ( sort keys %$Devel::ptkdb::subs_tree ) { |
|
1916
|
|
|
|
|
|
|
$self->{'sub_list'}->add($_, -text => $_) ; |
|
1917
|
|
|
|
|
|
|
} # end of top level loop |
|
1918
|
|
|
|
|
|
|
} |
|
1919
|
|
|
|
|
|
|
|
|
1920
|
|
|
|
|
|
|
sub setup_subs_page { |
|
1921
|
|
|
|
|
|
|
my($self) = @_ ; |
|
1922
|
|
|
|
|
|
|
|
|
1923
|
|
|
|
|
|
|
$self->{'subs_page_activated'} = 1 ; |
|
1924
|
|
|
|
|
|
|
|
|
1925
|
|
|
|
|
|
|
$self->{'sub_list'} = $self->{'subs_page'}->Scrolled('HList', -command => sub { $self->sub_list_cmd(@_) ; } ) ; |
|
1926
|
|
|
|
|
|
|
|
|
1927
|
|
|
|
|
|
|
$self->fill_subs_page() ; |
|
1928
|
|
|
|
|
|
|
|
|
1929
|
|
|
|
|
|
|
$self->{'sub_list'}->pack(-side => 'left', -fill => 'both', -expand => 1 |
|
1930
|
|
|
|
|
|
|
) ; |
|
1931
|
|
|
|
|
|
|
|
|
1932
|
|
|
|
|
|
|
$self->{'subs_list_cnt'} = scalar keys %DB::sub ; |
|
1933
|
|
|
|
|
|
|
|
|
1934
|
|
|
|
|
|
|
|
|
1935
|
|
|
|
|
|
|
} # end of setup_subs_page |
|
1936
|
|
|
|
|
|
|
|
|
1937
|
|
|
|
|
|
|
|
|
1938
|
|
|
|
|
|
|
sub check_search_request { |
|
1939
|
|
|
|
|
|
|
my($entry, $self, $searchButton, $regexBtn) = @_ ; |
|
1940
|
|
|
|
|
|
|
my($txt) = $entry->get ; |
|
1941
|
|
|
|
|
|
|
|
|
1942
|
|
|
|
|
|
|
if( $txt =~ /^\s*[0-9]+\s*$/ ) { |
|
1943
|
|
|
|
|
|
|
$self->DoGoto($entry) ; |
|
1944
|
|
|
|
|
|
|
return ; |
|
1945
|
|
|
|
|
|
|
} |
|
1946
|
|
|
|
|
|
|
|
|
1947
|
|
|
|
|
|
|
if( $txt =~ /\.\*/ ) { # common regex search pattern |
|
1948
|
|
|
|
|
|
|
$self->FindSearch($entry, $regexBtn, 1) ; |
|
1949
|
|
|
|
|
|
|
return ; |
|
1950
|
|
|
|
|
|
|
} |
|
1951
|
|
|
|
|
|
|
|
|
1952
|
|
|
|
|
|
|
# vanilla search |
|
1953
|
|
|
|
|
|
|
$self->FindSearch($entry, $searchButton, 0) ; |
|
1954
|
|
|
|
|
|
|
} |
|
1955
|
|
|
|
|
|
|
|
|
1956
|
|
|
|
|
|
|
sub setup_search_panel { |
|
1957
|
|
|
|
|
|
|
my ($self, $parent, @packArgs) = @_ ; |
|
1958
|
|
|
|
|
|
|
my ($frm, $srchBtn, $regexBtn, $entry) ; |
|
1959
|
|
|
|
|
|
|
|
|
1960
|
|
|
|
|
|
|
$frm = $parent->Frame() ; |
|
1961
|
|
|
|
|
|
|
|
|
1962
|
|
|
|
|
|
|
$frm->Button(-text => 'Goto', -command => sub { $self->DoGoto($entry) })->pack(-side => 'left') ; |
|
1963
|
|
|
|
|
|
|
$srchBtn = $frm->Button(-text => 'Search', -command => sub { $self->FindSearch($entry, $srchBtn, 0) ; } |
|
1964
|
|
|
|
|
|
|
)->pack(-side => 'left' ) ; |
|
1965
|
|
|
|
|
|
|
|
|
1966
|
|
|
|
|
|
|
$regexBtn = $frm->Button(-text => 'Regex', |
|
1967
|
|
|
|
|
|
|
-command => sub { $self->FindSearch($entry, $regexBtn, 1) ; } |
|
1968
|
|
|
|
|
|
|
)->pack(-side => 'left', |
|
1969
|
|
|
|
|
|
|
) ; |
|
1970
|
|
|
|
|
|
|
|
|
1971
|
|
|
|
|
|
|
|
|
1972
|
|
|
|
|
|
|
$entry = $frm->Entry(-width => 50)->pack(-side => 'left', -fill => 'both', -expand => 1) ; |
|
1973
|
|
|
|
|
|
|
|
|
1974
|
|
|
|
|
|
|
$entry->bind('', sub { check_search_request($entry, $self, $srchBtn, $regexBtn) ; } ) ; |
|
1975
|
|
|
|
|
|
|
|
|
1976
|
|
|
|
|
|
|
$frm->pack(@packArgs) ; |
|
1977
|
|
|
|
|
|
|
|
|
1978
|
|
|
|
|
|
|
} # end of setup search_panel |
|
1979
|
|
|
|
|
|
|
|
|
1980
|
|
|
|
|
|
|
sub setup_breakpts_page { |
|
1981
|
|
|
|
|
|
|
my ($self) = @_ ; |
|
1982
|
|
|
|
|
|
|
require Tk::Table ; |
|
1983
|
|
|
|
|
|
|
|
|
1984
|
|
|
|
|
|
|
$self->{'breakpts_page'} = $self->{'notebook'}->add("brkptspage", -label => "BrkPts") ; |
|
1985
|
|
|
|
|
|
|
|
|
1986
|
|
|
|
|
|
|
$self->{'breakpts_table'} = $self->{'breakpts_page'}->Table(-columns => 1, -scrollbars => 'se')-> |
|
1987
|
|
|
|
|
|
|
pack(-side => 'top', -fill => 'both', -expand => 1 |
|
1988
|
|
|
|
|
|
|
) ; |
|
1989
|
|
|
|
|
|
|
|
|
1990
|
|
|
|
|
|
|
$self->{'breakpts_table_data'} = { } ; # controls addressed by "fname:lineno" |
|
1991
|
|
|
|
|
|
|
|
|
1992
|
|
|
|
|
|
|
} # end of setup_breakpts_page |
|
1993
|
|
|
|
|
|
|
|
|
1994
|
|
|
|
|
|
|
sub setup_frames { |
|
1995
|
|
|
|
|
|
|
my ($self) = @_ ; |
|
1996
|
|
|
|
|
|
|
my $mw = $self->{'main_window'} ; |
|
1997
|
|
|
|
|
|
|
my ($txt, $place_holder, $frm) ; |
|
1998
|
|
|
|
|
|
|
require Tk::ROText ; |
|
1999
|
|
|
|
|
|
|
require Tk::NoteBook ; |
|
2000
|
|
|
|
|
|
|
require Tk::HList ; |
|
2001
|
|
|
|
|
|
|
require Tk::Balloon ; |
|
2002
|
|
|
|
|
|
|
require Tk::Adjuster ; |
|
2003
|
|
|
|
|
|
|
|
|
2004
|
|
|
|
|
|
|
# get the side that we want to put the code pane on |
|
2005
|
|
|
|
|
|
|
|
|
2006
|
|
|
|
|
|
|
my($codeSide) = $ENV{'PTKDB_CODE_SIDE'} || $mw->optionGet("codeside", "") || 'left' ; |
|
2007
|
|
|
|
|
|
|
|
|
2008
|
|
|
|
|
|
|
|
|
2009
|
|
|
|
|
|
|
|
|
2010
|
|
|
|
|
|
|
$mw->update ; # force geometry manager to map main_window |
|
2011
|
|
|
|
|
|
|
$frm = $mw->Frame(-width => $mw->reqwidth()) ; # frame for our code pane and search controls |
|
2012
|
|
|
|
|
|
|
|
|
2013
|
|
|
|
|
|
|
$self->setup_search_panel($frm, -side => 'top', -fill => 'x') ; |
|
2014
|
|
|
|
|
|
|
|
|
2015
|
|
|
|
|
|
|
# |
|
2016
|
|
|
|
|
|
|
# Text window for the code of our currently viewed file |
|
2017
|
|
|
|
|
|
|
# |
|
2018
|
|
|
|
|
|
|
$self->{'text'} = $frm->Scrolled('ROText', |
|
2019
|
|
|
|
|
|
|
-wrap => "none", |
|
2020
|
|
|
|
|
|
|
@Devel::ptkdb::scrollbar_cfg, |
|
2021
|
|
|
|
|
|
|
@Devel::ptkdb::code_text_font |
|
2022
|
|
|
|
|
|
|
) ; |
|
2023
|
|
|
|
|
|
|
|
|
2024
|
|
|
|
|
|
|
|
|
2025
|
|
|
|
|
|
|
$txt = $self->{'text'} ; |
|
2026
|
|
|
|
|
|
|
for( $txt->children ) { |
|
2027
|
|
|
|
|
|
|
next unless (ref $_) =~ /ROText$/ ; |
|
2028
|
|
|
|
|
|
|
$self->{'text'} = $_ ; |
|
2029
|
|
|
|
|
|
|
last ; |
|
2030
|
|
|
|
|
|
|
} |
|
2031
|
|
|
|
|
|
|
|
|
2032
|
|
|
|
|
|
|
$frm->packPropagate(0) ; |
|
2033
|
|
|
|
|
|
|
$txt->packPropagate(0) ; |
|
2034
|
|
|
|
|
|
|
|
|
2035
|
|
|
|
|
|
|
$frm->packAdjust(-side => $codeSide, -fill => 'both', -expand => 1) ; |
|
2036
|
|
|
|
|
|
|
$txt->pack(-side => 'left', -fill => 'both', -expand => 1) ; |
|
2037
|
|
|
|
|
|
|
|
|
2038
|
|
|
|
|
|
|
# $txt->form(-top => [ $self->{'menu_bar'} ], -left => '%0', -right => '%50') ; |
|
2039
|
|
|
|
|
|
|
# $frm->form(-top => [ $self->{'menu_bar'} ], -left => '%50', -right => '%100') ; |
|
2040
|
|
|
|
|
|
|
|
|
2041
|
|
|
|
|
|
|
$self->configure_text() ; |
|
2042
|
|
|
|
|
|
|
|
|
2043
|
|
|
|
|
|
|
# |
|
2044
|
|
|
|
|
|
|
# Notebook |
|
2045
|
|
|
|
|
|
|
# |
|
2046
|
|
|
|
|
|
|
|
|
2047
|
|
|
|
|
|
|
$self->{'notebook'} = $mw->NoteBook() ; |
|
2048
|
|
|
|
|
|
|
$self->{'notebook'}->packPropagate(0) ; |
|
2049
|
|
|
|
|
|
|
$self->{'notebook'}->pack(-side => $codeSide, -fill => 'both', -expand => 1) ; |
|
2050
|
|
|
|
|
|
|
|
|
2051
|
|
|
|
|
|
|
# |
|
2052
|
|
|
|
|
|
|
# an hlist for the data entries |
|
2053
|
|
|
|
|
|
|
# |
|
2054
|
|
|
|
|
|
|
$self->{'data_page'} = $self->{'notebook'}->add("datapage", -label => "Exprs") ; |
|
2055
|
|
|
|
|
|
|
|
|
2056
|
|
|
|
|
|
|
# |
|
2057
|
|
|
|
|
|
|
# frame, entry and label for quick expressions |
|
2058
|
|
|
|
|
|
|
# |
|
2059
|
|
|
|
|
|
|
my $frame = $self->{'data_page'}->Frame()->pack(-side => 'top', -fill => 'x') ; |
|
2060
|
|
|
|
|
|
|
|
|
2061
|
|
|
|
|
|
|
my $label = $frame->Label(-text => "Quick Expr:")->pack(-side => 'left') ; |
|
2062
|
|
|
|
|
|
|
|
|
2063
|
|
|
|
|
|
|
$self->{'quick_entry'} = $frame->Entry()->pack(-side => 'left', -fill => 'x', -expand => 1) ; |
|
2064
|
|
|
|
|
|
|
|
|
2065
|
|
|
|
|
|
|
$self->{'quick_entry'}->bind('', sub { $self->QuickExpr() ; } ) ; |
|
2066
|
|
|
|
|
|
|
|
|
2067
|
|
|
|
|
|
|
|
|
2068
|
|
|
|
|
|
|
# |
|
2069
|
|
|
|
|
|
|
# Entry widget for expressions and breakpoints |
|
2070
|
|
|
|
|
|
|
# |
|
2071
|
|
|
|
|
|
|
$frame = $self->{'data_page'}->Frame()->pack(-side => 'top', -fill => 'x') ; |
|
2072
|
|
|
|
|
|
|
|
|
2073
|
|
|
|
|
|
|
$label = $frame->Label(-text => "Enter Expr:")->pack(-side => 'left') ; |
|
2074
|
|
|
|
|
|
|
|
|
2075
|
|
|
|
|
|
|
$self->{'entry'} = $frame->Entry()->pack(-side => 'left', -fill => 'x', -expand => 1) ; |
|
2076
|
|
|
|
|
|
|
|
|
2077
|
|
|
|
|
|
|
$self->{'entry'}->bind('', sub { $self->EnterExpr() }) ; |
|
2078
|
|
|
|
|
|
|
|
|
2079
|
|
|
|
|
|
|
# |
|
2080
|
|
|
|
|
|
|
# Hlist for data expressions |
|
2081
|
|
|
|
|
|
|
# |
|
2082
|
|
|
|
|
|
|
|
|
2083
|
|
|
|
|
|
|
|
|
2084
|
|
|
|
|
|
|
$self->{data_list} = $self->{'data_page'}->Scrolled('HList', |
|
2085
|
|
|
|
|
|
|
@Devel::ptkdb::scrollbar_cfg, |
|
2086
|
|
|
|
|
|
|
separator => $Devel::ptkdb::pathSep, |
|
2087
|
|
|
|
|
|
|
@Devel::ptkdb::expression_text_font, |
|
2088
|
|
|
|
|
|
|
-command => \&Devel::ptkdb::expr_expand, |
|
2089
|
|
|
|
|
|
|
-selectmode => 'multiple' |
|
2090
|
|
|
|
|
|
|
) ; |
|
2091
|
|
|
|
|
|
|
|
|
2092
|
|
|
|
|
|
|
$self->{data_list}->pack(-side => 'top', -fill => 'both', -expand => 1 |
|
2093
|
|
|
|
|
|
|
) ; |
|
2094
|
|
|
|
|
|
|
|
|
2095
|
|
|
|
|
|
|
|
|
2096
|
|
|
|
|
|
|
$self->{'subs_page_activated'} = 0 ; |
|
2097
|
|
|
|
|
|
|
$self->{'subs_page'} = $self->{'notebook'}->add("subspage", -label => "Subs", -createcmd => sub { $self->setup_subs_page }) ; |
|
2098
|
|
|
|
|
|
|
|
|
2099
|
|
|
|
|
|
|
$self->setup_breakpts_page() ; |
|
2100
|
|
|
|
|
|
|
|
|
2101
|
|
|
|
|
|
|
} # end of setup_frames |
|
2102
|
|
|
|
|
|
|
|
|
2103
|
|
|
|
|
|
|
|
|
2104
|
|
|
|
|
|
|
|
|
2105
|
|
|
|
|
|
|
sub configure_text { |
|
2106
|
|
|
|
|
|
|
my($self) = @_ ; |
|
2107
|
|
|
|
|
|
|
my($txt, $mw) = ($self->{'text'}, $self->{'main_window'}) ; |
|
2108
|
|
|
|
|
|
|
my($place_holder) ; |
|
2109
|
|
|
|
|
|
|
|
|
2110
|
|
|
|
|
|
|
$self->{'expr_balloon'} = $txt->Balloon(); |
|
2111
|
|
|
|
|
|
|
$self->{'balloon_expr'} = ' ' ; # initial expression |
|
2112
|
|
|
|
|
|
|
|
|
2113
|
|
|
|
|
|
|
# If Data::Dumper is available setup a dumper for the balloon |
|
2114
|
|
|
|
|
|
|
|
|
2115
|
|
|
|
|
|
|
if ( $Devel::ptkdb::DataDumperAvailable ) { |
|
2116
|
|
|
|
|
|
|
$self->{'balloon_dumper'} = new Data::Dumper([$place_holder]) ; |
|
2117
|
|
|
|
|
|
|
$self->{'balloon_dumper'}->Terse(1) ; |
|
2118
|
|
|
|
|
|
|
$self->{'balloon_dumper'}->Indent($Devel::ptkdb::eval_dump_indent) ; |
|
2119
|
|
|
|
|
|
|
|
|
2120
|
|
|
|
|
|
|
$self->{'quick_dumper'} = new Data::Dumper([$place_holder]) ; |
|
2121
|
|
|
|
|
|
|
$self->{'quick_dumper'}->Terse(1) ; |
|
2122
|
|
|
|
|
|
|
$self->{'quick_dumper'}->Indent(0) ; |
|
2123
|
|
|
|
|
|
|
} |
|
2124
|
|
|
|
|
|
|
|
|
2125
|
|
|
|
|
|
|
$self->{'expr_ballon_msg'} = ' ' ; |
|
2126
|
|
|
|
|
|
|
|
|
2127
|
|
|
|
|
|
|
$self->{'expr_balloon'}->attach($txt, -initwait => 300, |
|
2128
|
|
|
|
|
|
|
-msg => \$self->{'expr_ballon_msg'}, |
|
2129
|
|
|
|
|
|
|
-balloonposition => 'mouse', |
|
2130
|
|
|
|
|
|
|
-postcommand => \&Devel::ptkdb::balloon_post, |
|
2131
|
|
|
|
|
|
|
-motioncommand => \&Devel::ptkdb::balloon_motion ) ; |
|
2132
|
|
|
|
|
|
|
|
|
2133
|
|
|
|
|
|
|
# tags for the text |
|
2134
|
|
|
|
|
|
|
|
|
2135
|
|
|
|
|
|
|
my @stopTagConfig = ( -foreground => 'white', -background => $mw->optionGet("stopcolor", "background") || $ENV{'PTKDB_STOP_TAG_COLOR'} || 'blue' ) ; |
|
2136
|
|
|
|
|
|
|
|
|
2137
|
|
|
|
|
|
|
my $stopFnt = $mw->optionGet("stopfont", "background") || $ENV{'PTKDB_STOP_TAG_FONT'} ; |
|
2138
|
|
|
|
|
|
|
push @stopTagConfig, ( -font => $stopFnt ) if $stopFnt ; # user may not have specified a font, if not, stay with the default |
|
2139
|
|
|
|
|
|
|
|
|
2140
|
|
|
|
|
|
|
$txt->tagConfigure('stoppt', @stopTagConfig) ; |
|
2141
|
|
|
|
|
|
|
$txt->tagConfigure('search_tag', "-background" => $mw->optionGet("searchtagcolor", "background") || "green") ; |
|
2142
|
|
|
|
|
|
|
|
|
2143
|
|
|
|
|
|
|
$txt->tagConfigure("breakableLine", -overstrike => 0) ; |
|
2144
|
|
|
|
|
|
|
$txt->tagConfigure("nonbreakableLine", -overstrike => 1) ; |
|
2145
|
|
|
|
|
|
|
$txt->tagConfigure("breaksetLine", -background => $mw->optionGet("breaktagcolor", "background") || $ENV{'PTKDB_BRKPT_COLOR'} || 'red') ; |
|
2146
|
|
|
|
|
|
|
$txt->tagConfigure("breakdisabledLine", -background => $mw->optionGet("disabledbreaktagcolor", "background") || $ENV{'PTKDB_DISABLEDBRKPT_COLOR'} || 'green') ; |
|
2147
|
|
|
|
|
|
|
|
|
2148
|
|
|
|
|
|
|
$txt->tagBind("breakableLine", '', [ \&Devel::ptkdb::set_breakpoint_tag, $self, Ev('@'), 1 ] ) ; |
|
2149
|
|
|
|
|
|
|
$txt->tagBind("breakableLine", '', [ \&Devel::ptkdb::set_breakpoint_tag, $self, Ev('@'), 0 ] ) ; |
|
2150
|
|
|
|
|
|
|
|
|
2151
|
|
|
|
|
|
|
$txt->tagBind("breaksetLine", '', [ \&Devel::ptkdb::clear_breakpoint_tag, $self, Ev('@') ] ) ; |
|
2152
|
|
|
|
|
|
|
$txt->tagBind("breaksetLine", '', [ \&Devel::ptkdb::change_breakpoint_tag, $self, Ev('@'), 0 ] ) ; |
|
2153
|
|
|
|
|
|
|
|
|
2154
|
|
|
|
|
|
|
$txt->tagBind("breakdisabledLine", '', [ \&Devel::ptkdb::clear_breakpoint_tag, $self, Ev('@') ] ) ; |
|
2155
|
|
|
|
|
|
|
$txt->tagBind("breakdisabledLine", '', [ \&Devel::ptkdb::change_breakpoint_tag, $self, Ev('@'), 1 ] ) ; |
|
2156
|
|
|
|
|
|
|
|
|
2157
|
|
|
|
|
|
|
} # end of configure_text |
|
2158
|
|
|
|
|
|
|
|
|
2159
|
|
|
|
|
|
|
|
|
2160
|
|
|
|
|
|
|
sub setup_options { |
|
2161
|
|
|
|
|
|
|
my ($self) = @_ ; |
|
2162
|
|
|
|
|
|
|
my $mw = $self->{main_window} ; |
|
2163
|
|
|
|
|
|
|
|
|
2164
|
|
|
|
|
|
|
return unless $mw->can('appname') ; |
|
2165
|
|
|
|
|
|
|
|
|
2166
|
|
|
|
|
|
|
$mw->appname("ptkdb") ; |
|
2167
|
|
|
|
|
|
|
$mw->optionAdd("stopcolor" => 'cyan', 60 ) ; |
|
2168
|
|
|
|
|
|
|
$mw->optionAdd("stopfont" => 'fixed', 60 ) ; |
|
2169
|
|
|
|
|
|
|
$mw->optionAdd("breaktag" => 'red', 60 ) ; |
|
2170
|
|
|
|
|
|
|
$mw->optionAdd("searchtagcolor" => 'green') ; |
|
2171
|
|
|
|
|
|
|
|
|
2172
|
|
|
|
|
|
|
$mw->optionClear ; # necessary to reload xresources |
|
2173
|
|
|
|
|
|
|
|
|
2174
|
|
|
|
|
|
|
} # end of setup_options |
|
2175
|
|
|
|
|
|
|
|
|
2176
|
|
|
|
|
|
|
sub DoAlert { |
|
2177
|
|
|
|
|
|
|
my($self, $msg, $title) = @_ ; |
|
2178
|
|
|
|
|
|
|
my($dlg) ; |
|
2179
|
|
|
|
|
|
|
my $okaySub = sub { |
|
2180
|
|
|
|
|
|
|
destroy $dlg ; |
|
2181
|
|
|
|
|
|
|
} ; |
|
2182
|
|
|
|
|
|
|
|
|
2183
|
|
|
|
|
|
|
$dlg = $self->{main_window}->Toplevel(-title => $title || "Alert", -overanchor => 'cursor') ; |
|
2184
|
|
|
|
|
|
|
|
|
2185
|
|
|
|
|
|
|
$dlg->Label( -text => $msg )->pack( -side => 'top' ) ; |
|
2186
|
|
|
|
|
|
|
|
|
2187
|
|
|
|
|
|
|
$dlg->Button( -text => "Okay", -command => $okaySub )->pack( -side => 'top' )->focus ; |
|
2188
|
|
|
|
|
|
|
$dlg->bind('', $okaySub) ; |
|
2189
|
|
|
|
|
|
|
|
|
2190
|
|
|
|
|
|
|
} # end of DoAlert |
|
2191
|
|
|
|
|
|
|
|
|
2192
|
|
|
|
|
|
|
sub simplePromptBox { |
|
2193
|
|
|
|
|
|
|
my ($self, $title, $defaultText, $okaySub, $cancelSub) = @_ ; |
|
2194
|
|
|
|
|
|
|
my ($top, $entry, $okayBtn) ; |
|
2195
|
|
|
|
|
|
|
|
|
2196
|
|
|
|
|
|
|
$top = $self->{main_window}->Toplevel(-title => $title, -overanchor => 'cursor' ) ; |
|
2197
|
|
|
|
|
|
|
|
|
2198
|
|
|
|
|
|
|
$Devel::ptkdb::promptString = $defaultText ; |
|
2199
|
|
|
|
|
|
|
|
|
2200
|
|
|
|
|
|
|
$entry = $top->Entry('-textvariable' => \$Devel::ptkdb::promptString)->pack(-side => 'top', -fill => 'both', -expand => 1) ; |
|
2201
|
|
|
|
|
|
|
|
|
2202
|
|
|
|
|
|
|
|
|
2203
|
|
|
|
|
|
|
$okayBtn = $top->Button( -text => "Okay", @Devel::ptkdb::button_font, -command => sub { &$okaySub() ; $top->destroy ;} |
|
2204
|
|
|
|
|
|
|
)->pack(-side => 'left', -fill => 'both', -expand => 1) ; |
|
2205
|
|
|
|
|
|
|
|
|
2206
|
|
|
|
|
|
|
$top->Button( -text => "Cancel", -command => sub { &$cancelSub() if $cancelSub ; $top->destroy() }, @Devel::ptkdb::button_font, |
|
2207
|
|
|
|
|
|
|
)->pack(-side => 'left', -fill => 'both', -expand => 1) ; |
|
2208
|
|
|
|
|
|
|
|
|
2209
|
|
|
|
|
|
|
$entry->icursor('end') ; |
|
2210
|
|
|
|
|
|
|
|
|
2211
|
|
|
|
|
|
|
$entry->selectionRange(0, 'end') if $entry->can('selectionRange') ; # some win32 Tk installations can't do this |
|
2212
|
|
|
|
|
|
|
|
|
2213
|
|
|
|
|
|
|
$entry->focus() ; |
|
2214
|
|
|
|
|
|
|
|
|
2215
|
|
|
|
|
|
|
return $top ; |
|
2216
|
|
|
|
|
|
|
|
|
2217
|
|
|
|
|
|
|
} # end of simplePromptBox |
|
2218
|
|
|
|
|
|
|
|
|
2219
|
|
|
|
|
|
|
sub get_entry_text { |
|
2220
|
|
|
|
|
|
|
my($self) = @_ ; |
|
2221
|
|
|
|
|
|
|
|
|
2222
|
|
|
|
|
|
|
return $self->{entry}->get() ; # get the text in the entry |
|
2223
|
|
|
|
|
|
|
} # end of get_entry_text |
|
2224
|
|
|
|
|
|
|
|
|
2225
|
|
|
|
|
|
|
|
|
2226
|
|
|
|
|
|
|
# |
|
2227
|
|
|
|
|
|
|
# Clear any text that is in the entry field. If there |
|
2228
|
|
|
|
|
|
|
# was any text in that field return it. If there |
|
2229
|
|
|
|
|
|
|
# was no text then return any selection that may be active. |
|
2230
|
|
|
|
|
|
|
# |
|
2231
|
|
|
|
|
|
|
sub clear_entry_text { |
|
2232
|
|
|
|
|
|
|
my($self) = @_ ; |
|
2233
|
|
|
|
|
|
|
my $str = $self->{'entry'}->get() ; |
|
2234
|
|
|
|
|
|
|
$self->{'entry'}->delete(0, 'end') ; |
|
2235
|
|
|
|
|
|
|
|
|
2236
|
|
|
|
|
|
|
# |
|
2237
|
|
|
|
|
|
|
# No String |
|
2238
|
|
|
|
|
|
|
# Empty String |
|
2239
|
|
|
|
|
|
|
# Or a string that is only whitespace |
|
2240
|
|
|
|
|
|
|
# |
|
2241
|
|
|
|
|
|
|
if( !$str || $str eq "" || $str =~ /^\s+$/ ) { |
|
2242
|
|
|
|
|
|
|
# |
|
2243
|
|
|
|
|
|
|
# If there is no string or the string is just white text |
|
2244
|
|
|
|
|
|
|
# Get the text in the selction( if any) |
|
2245
|
|
|
|
|
|
|
# |
|
2246
|
|
|
|
|
|
|
if( $self->{'text'}->tagRanges('sel') ) { # check to see if 'sel' tag exists (return undef value) |
|
2247
|
|
|
|
|
|
|
$str = $self->{'text'}->get("sel.first", "sel.last") ; # get the text between the 'first' and 'last' point of the sel (selection) tag |
|
2248
|
|
|
|
|
|
|
} |
|
2249
|
|
|
|
|
|
|
# If still no text, bring the focus to the entry |
|
2250
|
|
|
|
|
|
|
elsif( !$str || $str eq "" || $str =~ /^\s+$/ ) { |
|
2251
|
|
|
|
|
|
|
$self->{'entry'}->focus() ; |
|
2252
|
|
|
|
|
|
|
$str = "" ; |
|
2253
|
|
|
|
|
|
|
} |
|
2254
|
|
|
|
|
|
|
} |
|
2255
|
|
|
|
|
|
|
# |
|
2256
|
|
|
|
|
|
|
# Erase existing text |
|
2257
|
|
|
|
|
|
|
# |
|
2258
|
|
|
|
|
|
|
return $str ; |
|
2259
|
|
|
|
|
|
|
} # end of clear_entry_text |
|
2260
|
|
|
|
|
|
|
|
|
2261
|
|
|
|
|
|
|
sub brkPtCheckbutton { |
|
2262
|
|
|
|
|
|
|
my ($self, $fname, $idx, $brkPt) = @_ ; |
|
2263
|
|
|
|
|
|
|
my ($widg) ; |
|
2264
|
|
|
|
|
|
|
|
|
2265
|
|
|
|
|
|
|
change_breakpoint_tag($self->{'text'}, $self, "$idx.0", $brkPt->{'value'}) if $fname eq $self->{'current_file'} ; |
|
2266
|
|
|
|
|
|
|
|
|
2267
|
|
|
|
|
|
|
} # end of brkPtCheckbutton |
|
2268
|
|
|
|
|
|
|
|
|
2269
|
|
|
|
|
|
|
# |
|
2270
|
|
|
|
|
|
|
# insert a breakpoint control into our breakpoint list. |
|
2271
|
|
|
|
|
|
|
# returns a handle to the control |
|
2272
|
|
|
|
|
|
|
# |
|
2273
|
|
|
|
|
|
|
# Expression, if defined, is to be evaluated at the breakpoint |
|
2274
|
|
|
|
|
|
|
# and execution stopped if it is non-zero/defined. |
|
2275
|
|
|
|
|
|
|
# |
|
2276
|
|
|
|
|
|
|
# If action is defined && True then it will be evalled |
|
2277
|
|
|
|
|
|
|
# before continuing. |
|
2278
|
|
|
|
|
|
|
# |
|
2279
|
|
|
|
|
|
|
sub insertBreakpoint { |
|
2280
|
|
|
|
|
|
|
my ($self, $fname, @brks) = @_ ; |
|
2281
|
|
|
|
|
|
|
my ($btn, $cnt, $item) ; |
|
2282
|
|
|
|
|
|
|
|
|
2283
|
|
|
|
|
|
|
my($offset) ; |
|
2284
|
|
|
|
|
|
|
|
|
2285
|
|
|
|
|
|
|
local(*dbline) = $main::{'_<' . $fname} ; |
|
2286
|
|
|
|
|
|
|
|
|
2287
|
|
|
|
|
|
|
$offset = $dbline[1] =~ /use\s+.*Devel::_?ptkdb/ ? 1 : 0 ; |
|
2288
|
|
|
|
|
|
|
|
|
2289
|
|
|
|
|
|
|
while( @brks ) { |
|
2290
|
|
|
|
|
|
|
my($index, $value, $expression) = splice @brks, 0, 3 ; # take args 3 at a time |
|
2291
|
|
|
|
|
|
|
|
|
2292
|
|
|
|
|
|
|
my $brkPt = {} ; |
|
2293
|
|
|
|
|
|
|
my $txt = &DB::getdbtextline($fname, $index) ; |
|
2294
|
|
|
|
|
|
|
@$brkPt{'type', 'line', 'expr', 'value', 'fname', 'text'} = |
|
2295
|
|
|
|
|
|
|
('user', $index, $expression, $value, $fname, "$txt") ; |
|
2296
|
|
|
|
|
|
|
|
|
2297
|
|
|
|
|
|
|
&DB::setdbline($fname, $index + $offset, $brkPt) ; |
|
2298
|
|
|
|
|
|
|
$self->add_brkpt_to_brkpt_page($brkPt) ; |
|
2299
|
|
|
|
|
|
|
|
|
2300
|
|
|
|
|
|
|
next unless $fname eq $self->{'current_file'} ; |
|
2301
|
|
|
|
|
|
|
|
|
2302
|
|
|
|
|
|
|
$self->{'text'}->tagRemove("breakableLine", "$index.0", "$index.$Devel::ptkdb::linenumber_length") ; |
|
2303
|
|
|
|
|
|
|
$self->{'text'}->tagAdd($value ? "breaksetLine" : "breakdisabledLine", "$index.0", "$index.$Devel::ptkdb::linenumber_length") ; |
|
2304
|
|
|
|
|
|
|
} # end of loop |
|
2305
|
|
|
|
|
|
|
} # end of insertBreakpoint |
|
2306
|
|
|
|
|
|
|
|
|
2307
|
|
|
|
|
|
|
sub add_brkpt_to_brkpt_page { |
|
2308
|
|
|
|
|
|
|
my($self, $brkPt) = @_ ; |
|
2309
|
|
|
|
|
|
|
my($btn, $fname, $index, $frm, $upperFrame, $lowerFrame) ; |
|
2310
|
|
|
|
|
|
|
my ($row, $btnName, $width) ; |
|
2311
|
|
|
|
|
|
|
# |
|
2312
|
|
|
|
|
|
|
# Add the breakpoint to the breakpoints page |
|
2313
|
|
|
|
|
|
|
# |
|
2314
|
|
|
|
|
|
|
($fname, $index) = @$brkPt{'fname', 'line'} ; |
|
2315
|
|
|
|
|
|
|
return if exists $self->{'breakpts_table_data'}->{"$fname:$index"} ; |
|
2316
|
|
|
|
|
|
|
$self->{'brkPtCnt'} += 1 ; |
|
2317
|
|
|
|
|
|
|
|
|
2318
|
|
|
|
|
|
|
$btnName = $fname ; |
|
2319
|
|
|
|
|
|
|
$btnName =~ s/.*\/([^\/]*)$/$1/o ; |
|
2320
|
|
|
|
|
|
|
|
|
2321
|
|
|
|
|
|
|
# take the last leaf of the pathname |
|
2322
|
|
|
|
|
|
|
|
|
2323
|
|
|
|
|
|
|
$frm = $self->{'breakpts_table'}->Frame(-relief => 'raised') ; |
|
2324
|
|
|
|
|
|
|
$upperFrame = $frm->Frame()->pack(-side => 'top', '-fill' => 'x', -expand => 1) ; |
|
2325
|
|
|
|
|
|
|
|
|
2326
|
|
|
|
|
|
|
|
|
2327
|
|
|
|
|
|
|
$btn = $upperFrame->Checkbutton(-text => "$btnName:$index", |
|
2328
|
|
|
|
|
|
|
-variable => \$brkPt->{'value'}, # CAUTION value tracking |
|
2329
|
|
|
|
|
|
|
-command => sub { $self->brkPtCheckbutton($fname, $index, $brkPt) }) ; |
|
2330
|
|
|
|
|
|
|
|
|
2331
|
|
|
|
|
|
|
$btn->pack(-side => 'left') ; |
|
2332
|
|
|
|
|
|
|
|
|
2333
|
|
|
|
|
|
|
$btn = $upperFrame->Button(-text => "Delete", -command => sub { $self->removeBreakpoint($fname, $index) ; } ) ; |
|
2334
|
|
|
|
|
|
|
$btn->pack(-side => 'left', -fill => 'x', -expand => 1) ; |
|
2335
|
|
|
|
|
|
|
|
|
2336
|
|
|
|
|
|
|
$btn = $upperFrame->Button(-text => "Goto", -command => sub { $self->set_file($fname, $index) ; } ) ; |
|
2337
|
|
|
|
|
|
|
$btn->pack(-side => 'left', -fill => 'x', -expand => 1) ; |
|
2338
|
|
|
|
|
|
|
|
|
2339
|
|
|
|
|
|
|
$lowerFrame = $frm->Frame()->pack(-side => 'top', '-fill' => 'x', -expand => 1) ; |
|
2340
|
|
|
|
|
|
|
|
|
2341
|
|
|
|
|
|
|
$lowerFrame->Label(-text => "Cond:")->pack(-side => 'left') ; |
|
2342
|
|
|
|
|
|
|
|
|
2343
|
|
|
|
|
|
|
$btn = $lowerFrame->Entry(-textvariable => \$brkPt->{'expr'}) ; |
|
2344
|
|
|
|
|
|
|
$btn->pack(-side => 'left', -fill => 'x', -expand => 1) ; |
|
2345
|
|
|
|
|
|
|
|
|
2346
|
|
|
|
|
|
|
$frm->pack(-side => 'top', -fill => 'x', -expand => 1) ; |
|
2347
|
|
|
|
|
|
|
|
|
2348
|
|
|
|
|
|
|
$row = pop @{$self->{'brkPtSlots'}} or $row = $self->{'brkPtCnt'} ; |
|
2349
|
|
|
|
|
|
|
|
|
2350
|
|
|
|
|
|
|
$self->{'breakpts_table'}->put($row, 1, $frm) ; |
|
2351
|
|
|
|
|
|
|
|
|
2352
|
|
|
|
|
|
|
$self->{'breakpts_table_data'}->{"$fname:$index"}->{'frm'} = $frm ; |
|
2353
|
|
|
|
|
|
|
$self->{'breakpts_table_data'}->{"$fname:$index"}->{'row'} = $row ; |
|
2354
|
|
|
|
|
|
|
|
|
2355
|
|
|
|
|
|
|
$self->{'main_window'}->update ; |
|
2356
|
|
|
|
|
|
|
|
|
2357
|
|
|
|
|
|
|
$width = $frm->width ; |
|
2358
|
|
|
|
|
|
|
|
|
2359
|
|
|
|
|
|
|
if ( $width > $self->{'breakpts_table'}->width ) { |
|
2360
|
|
|
|
|
|
|
$self->{'notebook'}->configure(-width => $width) ; |
|
2361
|
|
|
|
|
|
|
} |
|
2362
|
|
|
|
|
|
|
|
|
2363
|
|
|
|
|
|
|
} # end of add_brkpt_to_brkpt_page |
|
2364
|
|
|
|
|
|
|
|
|
2365
|
|
|
|
|
|
|
sub remove_brkpt_from_brkpt_page { |
|
2366
|
|
|
|
|
|
|
my($self, $fname, $idx) = @_ ; |
|
2367
|
|
|
|
|
|
|
my($table) ; |
|
2368
|
|
|
|
|
|
|
|
|
2369
|
|
|
|
|
|
|
$table = $self->{'breakpts_table'} ; |
|
2370
|
|
|
|
|
|
|
|
|
2371
|
|
|
|
|
|
|
# Delete the breakpoint control in the breakpoints window |
|
2372
|
|
|
|
|
|
|
|
|
2373
|
|
|
|
|
|
|
$table->put($self->{'breakpts_table_data'}->{"$fname:$idx"}->{'row'}, 1) ; # delete? |
|
2374
|
|
|
|
|
|
|
|
|
2375
|
|
|
|
|
|
|
# |
|
2376
|
|
|
|
|
|
|
# Add this now empty slot to the list of ones we have open |
|
2377
|
|
|
|
|
|
|
# |
|
2378
|
|
|
|
|
|
|
|
|
2379
|
|
|
|
|
|
|
push @{$self->{'brkPtSlots'}}, $self->{'breakpts_table_data'}->{"$fname:$idx"}->{'row'} ; |
|
2380
|
|
|
|
|
|
|
|
|
2381
|
|
|
|
|
|
|
$self->{'brkPtSlots'} = [ sort { $b <=> $a } @{$self->{'brkPtSlots'}} ] ; |
|
2382
|
|
|
|
|
|
|
|
|
2383
|
|
|
|
|
|
|
delete $self->{'breakpts_table_data'}->{"$fname:$idx"} ; |
|
2384
|
|
|
|
|
|
|
|
|
2385
|
|
|
|
|
|
|
$self->{'brkPtCnt'} -= 1 ; |
|
2386
|
|
|
|
|
|
|
|
|
2387
|
|
|
|
|
|
|
} # end of remove_brkpt_from_brkpt_page |
|
2388
|
|
|
|
|
|
|
|
|
2389
|
|
|
|
|
|
|
|
|
2390
|
|
|
|
|
|
|
# |
|
2391
|
|
|
|
|
|
|
# Supporting the "Run To Here..." command |
|
2392
|
|
|
|
|
|
|
# |
|
2393
|
|
|
|
|
|
|
sub insertTempBreakpoint { |
|
2394
|
|
|
|
|
|
|
my ($self, $fname, $index) = @_ ; |
|
2395
|
|
|
|
|
|
|
my($offset) ; |
|
2396
|
|
|
|
|
|
|
local(*dbline) = $main::{'_<' . $fname} ; |
|
2397
|
|
|
|
|
|
|
|
|
2398
|
|
|
|
|
|
|
$offset = $dbline[1] =~ /use\s+.*Devel::_?ptkdb/ ? 1 : 0 ; |
|
2399
|
|
|
|
|
|
|
|
|
2400
|
|
|
|
|
|
|
return if( &DB::getdbline($fname, $index + $offset) ) ; # we already have a breakpoint here |
|
2401
|
|
|
|
|
|
|
|
|
2402
|
|
|
|
|
|
|
&DB::setdbline($fname, $index + $offset, {'type' => 'temp', 'line' => $index, 'value' => 1 } ) ; |
|
2403
|
|
|
|
|
|
|
|
|
2404
|
|
|
|
|
|
|
} # end of insertTempBreakpoint |
|
2405
|
|
|
|
|
|
|
|
|
2406
|
|
|
|
|
|
|
sub reinsertBreakpoints { |
|
2407
|
|
|
|
|
|
|
my ($self, $fname) = @_ ; |
|
2408
|
|
|
|
|
|
|
my ($brkPt) ; |
|
2409
|
|
|
|
|
|
|
|
|
2410
|
|
|
|
|
|
|
foreach $brkPt ( &DB::getbreakpoints($fname) ) { |
|
2411
|
|
|
|
|
|
|
# |
|
2412
|
|
|
|
|
|
|
# Our breakpoints are indexed by line |
|
2413
|
|
|
|
|
|
|
# therefore we can have 'gaps' where there |
|
2414
|
|
|
|
|
|
|
# lines, but not breaks set for them. |
|
2415
|
|
|
|
|
|
|
# |
|
2416
|
|
|
|
|
|
|
next unless defined $brkPt ; |
|
2417
|
|
|
|
|
|
|
|
|
2418
|
|
|
|
|
|
|
$self->insertBreakpoint($fname, @$brkPt{'line', 'value', 'expr'}) if( $brkPt->{'type'} eq 'user' ) ; |
|
2419
|
|
|
|
|
|
|
$self->insertTempBreakpoint($fname, $brkPt->{line}) if( $brkPt->{'type'} eq 'temp' ) ; |
|
2420
|
|
|
|
|
|
|
} # end of reinsert loop |
|
2421
|
|
|
|
|
|
|
|
|
2422
|
|
|
|
|
|
|
} # end of reinsertBreakpoints |
|
2423
|
|
|
|
|
|
|
|
|
2424
|
|
|
|
|
|
|
sub removeBreakpointTags { |
|
2425
|
|
|
|
|
|
|
my ($self, @brkPts) = @_ ; |
|
2426
|
|
|
|
|
|
|
my($idx, $brkPt) ; |
|
2427
|
|
|
|
|
|
|
|
|
2428
|
|
|
|
|
|
|
foreach $brkPt (@brkPts) { |
|
2429
|
|
|
|
|
|
|
|
|
2430
|
|
|
|
|
|
|
$idx = $brkPt->{'line'} ; |
|
2431
|
|
|
|
|
|
|
|
|
2432
|
|
|
|
|
|
|
if ( $brkPt->{'value'} ) { |
|
2433
|
|
|
|
|
|
|
$self->{'text'}->tagRemove("breaksetLine", "$idx.0", "$idx.$Devel::ptkdb::linenumber_length") ; |
|
2434
|
|
|
|
|
|
|
} |
|
2435
|
|
|
|
|
|
|
else { |
|
2436
|
|
|
|
|
|
|
$self->{'text'}->tagRemove("breakdisabledLine", "$idx.0", "$idx.$Devel::ptkdb::linenumber_length") ; |
|
2437
|
|
|
|
|
|
|
} |
|
2438
|
|
|
|
|
|
|
|
|
2439
|
|
|
|
|
|
|
$self->{'text'}->tagAdd("breakableLine", "$idx.0", "$idx.$Devel::ptkdb::linenumber_length") ; |
|
2440
|
|
|
|
|
|
|
} |
|
2441
|
|
|
|
|
|
|
} # end of removeBreakpointTags |
|
2442
|
|
|
|
|
|
|
|
|
2443
|
|
|
|
|
|
|
# |
|
2444
|
|
|
|
|
|
|
# Remove a breakpoint from the current window |
|
2445
|
|
|
|
|
|
|
# |
|
2446
|
|
|
|
|
|
|
sub removeBreakpoint { |
|
2447
|
|
|
|
|
|
|
my ($self, $fname, @idx) = @_ ; |
|
2448
|
|
|
|
|
|
|
my ($idx, $chkIdx, $i, $j, $info) ; |
|
2449
|
|
|
|
|
|
|
my($offset) ; |
|
2450
|
|
|
|
|
|
|
local(*dbline) = $main::{'_<' . $fname} ; |
|
2451
|
|
|
|
|
|
|
|
|
2452
|
|
|
|
|
|
|
$offset = $dbline[1] =~ /use\s+.*Devel::_?ptkdb/ ? 1 : 0 ; |
|
2453
|
|
|
|
|
|
|
|
|
2454
|
|
|
|
|
|
|
foreach $idx (@idx) { # end of removal loop |
|
2455
|
|
|
|
|
|
|
next unless defined $idx ; |
|
2456
|
|
|
|
|
|
|
my $brkPt = &DB::getdbline($fname, $idx + $offset) ; |
|
2457
|
|
|
|
|
|
|
next unless $brkPt ; # if we do not have an entry |
|
2458
|
|
|
|
|
|
|
&DB::cleardbline($fname, $idx + $offset) ; |
|
2459
|
|
|
|
|
|
|
|
|
2460
|
|
|
|
|
|
|
$self->remove_brkpt_from_brkpt_page($fname, $idx) ; |
|
2461
|
|
|
|
|
|
|
|
|
2462
|
|
|
|
|
|
|
next unless $brkPt->{fname} eq $self->{'current_file'} ; # if this isn't our current file there will be no controls |
|
2463
|
|
|
|
|
|
|
|
|
2464
|
|
|
|
|
|
|
# Delete the ext associated with the breakpoint expression (if any) |
|
2465
|
|
|
|
|
|
|
|
|
2466
|
|
|
|
|
|
|
$self->removeBreakpointTags($brkPt) ; |
|
2467
|
|
|
|
|
|
|
} # end of remove loop |
|
2468
|
|
|
|
|
|
|
|
|
2469
|
|
|
|
|
|
|
return ; |
|
2470
|
|
|
|
|
|
|
} # end of removeBreakpoint |
|
2471
|
|
|
|
|
|
|
|
|
2472
|
|
|
|
|
|
|
sub removeAllBreakpoints { |
|
2473
|
|
|
|
|
|
|
my ($self, $fname) = @_ ; |
|
2474
|
|
|
|
|
|
|
|
|
2475
|
|
|
|
|
|
|
$self->removeBreakpoint($fname, &DB::getdblineindexes($fname)) ; |
|
2476
|
|
|
|
|
|
|
|
|
2477
|
|
|
|
|
|
|
} # end of removeAllBreakpoints |
|
2478
|
|
|
|
|
|
|
|
|
2479
|
|
|
|
|
|
|
# |
|
2480
|
|
|
|
|
|
|
# Delete expressions prior to an update |
|
2481
|
|
|
|
|
|
|
# |
|
2482
|
|
|
|
|
|
|
sub deleteAllExprs { |
|
2483
|
|
|
|
|
|
|
my ($self) = @_ ; |
|
2484
|
|
|
|
|
|
|
$self->{'data_list'}->delete('all') ; |
|
2485
|
|
|
|
|
|
|
} # end of deleteAllExprs |
|
2486
|
|
|
|
|
|
|
|
|
2487
|
|
|
|
|
|
|
sub EnterExpr { |
|
2488
|
|
|
|
|
|
|
my ($self) = @_ ; |
|
2489
|
|
|
|
|
|
|
my $str = $self->clear_entry_text() ; |
|
2490
|
|
|
|
|
|
|
if( $str && $str ne "" && $str !~ /^\s+$/ ) { # if there is an expression and it's more than white space |
|
2491
|
|
|
|
|
|
|
$self->{'expr'} = $str ; |
|
2492
|
|
|
|
|
|
|
$self->{'event'} = 'expr' ; |
|
2493
|
|
|
|
|
|
|
} |
|
2494
|
|
|
|
|
|
|
} # end of EnterExpr |
|
2495
|
|
|
|
|
|
|
|
|
2496
|
|
|
|
|
|
|
# |
|
2497
|
|
|
|
|
|
|
# |
|
2498
|
|
|
|
|
|
|
# |
|
2499
|
|
|
|
|
|
|
sub QuickExpr { |
|
2500
|
|
|
|
|
|
|
my ($self) = @_ ; |
|
2501
|
|
|
|
|
|
|
|
|
2502
|
|
|
|
|
|
|
my $str = $self->{'quick_entry'}->get() ; |
|
2503
|
|
|
|
|
|
|
|
|
2504
|
|
|
|
|
|
|
if( $str && $str ne "" && $str !~ /^\s+$/ ) { # if there is an expression and it's more than white space |
|
2505
|
|
|
|
|
|
|
$self->{'qexpr'} = $str ; |
|
2506
|
|
|
|
|
|
|
$self->{'event'} = 'qexpr' ; |
|
2507
|
|
|
|
|
|
|
} |
|
2508
|
|
|
|
|
|
|
} # end of QuickExpr |
|
2509
|
|
|
|
|
|
|
|
|
2510
|
|
|
|
|
|
|
sub deleteExpr { |
|
2511
|
|
|
|
|
|
|
my ($self) = @_ ; |
|
2512
|
|
|
|
|
|
|
my ($entry, $i, @indexes) ; |
|
2513
|
|
|
|
|
|
|
my @sList = $self->{'data_list'}->info('select') ; |
|
2514
|
|
|
|
|
|
|
|
|
2515
|
|
|
|
|
|
|
# |
|
2516
|
|
|
|
|
|
|
# if we're deleteing a top level expression |
|
2517
|
|
|
|
|
|
|
# we have to take it out of the list of expressions |
|
2518
|
|
|
|
|
|
|
# |
|
2519
|
|
|
|
|
|
|
|
|
2520
|
|
|
|
|
|
|
foreach $entry ( @sList ) { |
|
2521
|
|
|
|
|
|
|
next if ($entry =~ /\//) ; # goto next expression if we're not a top level ( expr/entry) |
|
2522
|
|
|
|
|
|
|
$i = 0 ; |
|
2523
|
|
|
|
|
|
|
grep { push @indexes, $i if ($_->{'expr'} eq $entry) ; $i++ ; } @{$self->{'expr_list'}} ; |
|
2524
|
|
|
|
|
|
|
} # end of check loop |
|
2525
|
|
|
|
|
|
|
|
|
2526
|
|
|
|
|
|
|
# now take out our list of indexes ; |
|
2527
|
|
|
|
|
|
|
|
|
2528
|
|
|
|
|
|
|
for( 0..$#indexes ) { |
|
2529
|
|
|
|
|
|
|
splice @{$self->{'expr_list'}}, $indexes[$_] - $_, 1 ; |
|
2530
|
|
|
|
|
|
|
} |
|
2531
|
|
|
|
|
|
|
|
|
2532
|
|
|
|
|
|
|
for( @sList ) { |
|
2533
|
|
|
|
|
|
|
$self->{'data_list'}->delete('entry', $_) ; |
|
2534
|
|
|
|
|
|
|
} |
|
2535
|
|
|
|
|
|
|
} # end of deleteExpr |
|
2536
|
|
|
|
|
|
|
|
|
2537
|
|
|
|
|
|
|
sub fixExprPath { |
|
2538
|
|
|
|
|
|
|
my(@pathList) = @_ ; |
|
2539
|
|
|
|
|
|
|
|
|
2540
|
|
|
|
|
|
|
for (@pathList) { |
|
2541
|
|
|
|
|
|
|
s/$Devel::ptkdb::pathSep/$Devel::ptkdb::pathSepReplacement/go ; |
|
2542
|
|
|
|
|
|
|
} # end of path list |
|
2543
|
|
|
|
|
|
|
|
|
2544
|
|
|
|
|
|
|
return $pathList[0] unless wantarray ; |
|
2545
|
|
|
|
|
|
|
return @pathList ; |
|
2546
|
|
|
|
|
|
|
|
|
2547
|
|
|
|
|
|
|
} # end of fixExprPath |
|
2548
|
|
|
|
|
|
|
|
|
2549
|
|
|
|
|
|
|
## |
|
2550
|
|
|
|
|
|
|
## Inserts an expression($theRef) into an HList Widget($dl). If the expression |
|
2551
|
|
|
|
|
|
|
## is an array, blessed array, hash, or blessed hash(typical object), then this |
|
2552
|
|
|
|
|
|
|
## routine is called recursively, adding the members to the next level of heirarchy, |
|
2553
|
|
|
|
|
|
|
## prefixing array members with a [idx] and the hash members with the key name. |
|
2554
|
|
|
|
|
|
|
## This continues until the entire expression is decomposed to it's atomic constituents. |
|
2555
|
|
|
|
|
|
|
## Protection is given(with $reusedRefs) to ensure that 'circular' references within |
|
2556
|
|
|
|
|
|
|
## arrays or hashes(i.e. where a member of a array or hash contains a reference to a |
|
2557
|
|
|
|
|
|
|
## parent element within the heirarchy. |
|
2558
|
|
|
|
|
|
|
## |
|
2559
|
|
|
|
|
|
|
# |
|
2560
|
|
|
|
|
|
|
# Returns 1 if sucessfully added 0 if not |
|
2561
|
|
|
|
|
|
|
# |
|
2562
|
|
|
|
|
|
|
sub insertExpr { |
|
2563
|
|
|
|
|
|
|
my($self, $reusedRefs, $dl, $theRef, $name, $depth, $dirPath) = @_ ; |
|
2564
|
|
|
|
|
|
|
my($label, $type, $result, $selfCnt, @circRefs) ; |
|
2565
|
|
|
|
|
|
|
local($^W) = 0 ; # spare us uncessary warnings about comparing strings with == |
|
2566
|
|
|
|
|
|
|
|
|
2567
|
|
|
|
|
|
|
# |
|
2568
|
|
|
|
|
|
|
# Add data new data entries to the bottom |
|
2569
|
|
|
|
|
|
|
# |
|
2570
|
|
|
|
|
|
|
$dirPath = "" unless defined $dirPath ; |
|
2571
|
|
|
|
|
|
|
|
|
2572
|
|
|
|
|
|
|
$label = "" ; |
|
2573
|
|
|
|
|
|
|
$selfCnt = 0 ; |
|
2574
|
|
|
|
|
|
|
|
|
2575
|
|
|
|
|
|
|
while( ref $theRef eq 'SCALAR' ) { |
|
2576
|
|
|
|
|
|
|
$theRef = $$theRef ; |
|
2577
|
|
|
|
|
|
|
} |
|
2578
|
|
|
|
|
|
|
REF_CHECK: for( ; ; ) { |
|
2579
|
|
|
|
|
|
|
push @circRefs, $theRef ; |
|
2580
|
|
|
|
|
|
|
$type = ref $theRef ; |
|
2581
|
|
|
|
|
|
|
last unless ($type eq "REF") ; |
|
2582
|
|
|
|
|
|
|
$theRef = $$theRef ; # dref again |
|
2583
|
|
|
|
|
|
|
|
|
2584
|
|
|
|
|
|
|
$label .= "\\" ; # append a |
|
2585
|
|
|
|
|
|
|
if( grep $_ == $theRef, @circRefs ) { |
|
2586
|
|
|
|
|
|
|
$label .= "(circular)" ; |
|
2587
|
|
|
|
|
|
|
last ; |
|
2588
|
|
|
|
|
|
|
} |
|
2589
|
|
|
|
|
|
|
} |
|
2590
|
|
|
|
|
|
|
|
|
2591
|
|
|
|
|
|
|
if( !$type || $type eq "" || $type eq "GLOB" || $type eq "CODE") { |
|
2592
|
|
|
|
|
|
|
eval { |
|
2593
|
|
|
|
|
|
|
if( !defined $theRef ) { |
|
2594
|
|
|
|
|
|
|
$dl->add($dirPath . $name, -text => "$name = $label" . "undef") ; |
|
2595
|
|
|
|
|
|
|
} |
|
2596
|
|
|
|
|
|
|
else { |
|
2597
|
|
|
|
|
|
|
$dl->add($dirPath . $name, -text => "$name = $label$theRef") ; |
|
2598
|
|
|
|
|
|
|
} |
|
2599
|
|
|
|
|
|
|
} ; |
|
2600
|
|
|
|
|
|
|
$self->DoAlert($@), return 0 if $@ ; |
|
2601
|
|
|
|
|
|
|
return 1 ; |
|
2602
|
|
|
|
|
|
|
} |
|
2603
|
|
|
|
|
|
|
|
|
2604
|
|
|
|
|
|
|
if( $type eq 'ARRAY' or "$theRef" =~ /ARRAY/ ) { |
|
2605
|
|
|
|
|
|
|
my ($r, $idx) ; |
|
2606
|
|
|
|
|
|
|
$idx = 0 ; |
|
2607
|
|
|
|
|
|
|
eval { |
|
2608
|
|
|
|
|
|
|
$dl->add($dirPath . $name, -text => "$name = $theRef") ; |
|
2609
|
|
|
|
|
|
|
} ; |
|
2610
|
|
|
|
|
|
|
if( $@ ) { |
|
2611
|
|
|
|
|
|
|
$self->DoAlert($@) ; |
|
2612
|
|
|
|
|
|
|
return 0 ; |
|
2613
|
|
|
|
|
|
|
} |
|
2614
|
|
|
|
|
|
|
$result = 1 ; |
|
2615
|
|
|
|
|
|
|
foreach $r ( @{$theRef} ) { |
|
2616
|
|
|
|
|
|
|
|
|
2617
|
|
|
|
|
|
|
if( grep $_ == $r, @$reusedRefs ) { # check to make sure that we're not doing a single level self reference |
|
2618
|
|
|
|
|
|
|
eval { |
|
2619
|
|
|
|
|
|
|
$dl->add($dirPath . fixExprPath($name) . $Devel::ptkdb::pathSep . "__ptkdb_self_path" . $selfCnt++, -text => "[$idx] = $r REUSED ADDR") ; |
|
2620
|
|
|
|
|
|
|
} ; |
|
2621
|
|
|
|
|
|
|
$self->DoAlert($@) if( $@ ) ; |
|
2622
|
|
|
|
|
|
|
next ; |
|
2623
|
|
|
|
|
|
|
} |
|
2624
|
|
|
|
|
|
|
|
|
2625
|
|
|
|
|
|
|
push @$reusedRefs, $r ; |
|
2626
|
|
|
|
|
|
|
$result = $self->insertExpr($reusedRefs, $dl, $r, "[$idx]", $depth-1, $dirPath . fixExprPath($name) . $Devel::ptkdb::pathSep) unless $depth == 0 ; |
|
2627
|
|
|
|
|
|
|
pop @$reusedRefs ; |
|
2628
|
|
|
|
|
|
|
|
|
2629
|
|
|
|
|
|
|
return 0 unless $result ; |
|
2630
|
|
|
|
|
|
|
$idx += 1 ; |
|
2631
|
|
|
|
|
|
|
} |
|
2632
|
|
|
|
|
|
|
return 1 ; |
|
2633
|
|
|
|
|
|
|
} # end of array case |
|
2634
|
|
|
|
|
|
|
|
|
2635
|
|
|
|
|
|
|
if( "$theRef" !~ /HASH\050\060x[0-9a-f]*\051/o ) { |
|
2636
|
|
|
|
|
|
|
eval { |
|
2637
|
|
|
|
|
|
|
$dl->add($dirPath . fixExprPath($name), -text => "$name = $theRef") ; |
|
2638
|
|
|
|
|
|
|
} ; |
|
2639
|
|
|
|
|
|
|
if( $@ ) { |
|
2640
|
|
|
|
|
|
|
$self->DoAlert($@) ; |
|
2641
|
|
|
|
|
|
|
return 0 ; |
|
2642
|
|
|
|
|
|
|
} |
|
2643
|
|
|
|
|
|
|
return 1 ; |
|
2644
|
|
|
|
|
|
|
} |
|
2645
|
|
|
|
|
|
|
# |
|
2646
|
|
|
|
|
|
|
# Anything else at this point is |
|
2647
|
|
|
|
|
|
|
# either a 'HASH' or an object |
|
2648
|
|
|
|
|
|
|
# of some kind. |
|
2649
|
|
|
|
|
|
|
# |
|
2650
|
|
|
|
|
|
|
my($r, @theKeys, $idx) ; |
|
2651
|
|
|
|
|
|
|
$idx = 0 ; |
|
2652
|
|
|
|
|
|
|
@theKeys = sort keys %{$theRef} ; |
|
2653
|
|
|
|
|
|
|
$dl->add($dirPath . $name, -text => "$name = " . "$theRef") ; |
|
2654
|
|
|
|
|
|
|
$result = 1 ; |
|
2655
|
|
|
|
|
|
|
|
|
2656
|
|
|
|
|
|
|
foreach $r ( @$theRef{@theKeys} ) { # slice out the values with the sorted list |
|
2657
|
|
|
|
|
|
|
|
|
2658
|
|
|
|
|
|
|
if( grep $_ == $r, @$reusedRefs ) { # check to make sure that we're not doing a single level self reference |
|
2659
|
|
|
|
|
|
|
eval { |
|
2660
|
|
|
|
|
|
|
$dl->add($dirPath . fixExprPath($name) . $Devel::ptkdb::pathSep . "__ptkdb_self_path" . $selfCnt++, -text => "$theKeys[$idx++] = $r REUSED ADDR") ; |
|
2661
|
|
|
|
|
|
|
} ; |
|
2662
|
|
|
|
|
|
|
print "bad path $@\n" if( $@ ) ; |
|
2663
|
|
|
|
|
|
|
next ; |
|
2664
|
|
|
|
|
|
|
} |
|
2665
|
|
|
|
|
|
|
|
|
2666
|
|
|
|
|
|
|
push @$reusedRefs, $r ; |
|
2667
|
|
|
|
|
|
|
|
|
2668
|
|
|
|
|
|
|
$result = $self->insertExpr($reusedRefs, # recursion protection |
|
2669
|
|
|
|
|
|
|
$dl, # data list widget |
|
2670
|
|
|
|
|
|
|
$r, # reference whose value is displayed |
|
2671
|
|
|
|
|
|
|
$theKeys[$idx], # name |
|
2672
|
|
|
|
|
|
|
$depth-1, # remaining expansion depth |
|
2673
|
|
|
|
|
|
|
$dirPath . $name . $Devel::ptkdb::pathSep # path to add to |
|
2674
|
|
|
|
|
|
|
) unless $depth == 0 ; |
|
2675
|
|
|
|
|
|
|
|
|
2676
|
|
|
|
|
|
|
pop @$reusedRefs ; |
|
2677
|
|
|
|
|
|
|
|
|
2678
|
|
|
|
|
|
|
return 0 unless $result ; |
|
2679
|
|
|
|
|
|
|
$idx += 1 ; |
|
2680
|
|
|
|
|
|
|
} # end of ref add loop |
|
2681
|
|
|
|
|
|
|
|
|
2682
|
|
|
|
|
|
|
return 1 ; |
|
2683
|
|
|
|
|
|
|
} # end of insertExpr |
|
2684
|
|
|
|
|
|
|
|
|
2685
|
|
|
|
|
|
|
# |
|
2686
|
|
|
|
|
|
|
# We're setting the line where we are stopped. |
|
2687
|
|
|
|
|
|
|
# Create a tag for this and set it as bold. |
|
2688
|
|
|
|
|
|
|
# |
|
2689
|
|
|
|
|
|
|
sub set_line { |
|
2690
|
|
|
|
|
|
|
my ($self, $lineno) = @_ ; |
|
2691
|
|
|
|
|
|
|
my $text = $self->{'text'} ; |
|
2692
|
|
|
|
|
|
|
|
|
2693
|
|
|
|
|
|
|
return if( $lineno <= 0 ) ; |
|
2694
|
|
|
|
|
|
|
|
|
2695
|
|
|
|
|
|
|
if( $self->{current_line} > 0 ) { |
|
2696
|
|
|
|
|
|
|
$text->tagRemove('stoppt', "$self->{current_line}.0 linestart", "$self->{current_line}.0 lineend") ; |
|
2697
|
|
|
|
|
|
|
} |
|
2698
|
|
|
|
|
|
|
$self->{current_line} = $lineno - $self->{'line_offset'} ; |
|
2699
|
|
|
|
|
|
|
$text->tagAdd('stoppt', "$self->{current_line}.0 linestart", "$self->{current_line}.0 lineend") ; |
|
2700
|
|
|
|
|
|
|
|
|
2701
|
|
|
|
|
|
|
$self->{'text'}->see("$self->{current_line}.0 linestart") ; |
|
2702
|
|
|
|
|
|
|
} # end of set_line |
|
2703
|
|
|
|
|
|
|
|
|
2704
|
|
|
|
|
|
|
# |
|
2705
|
|
|
|
|
|
|
# Set the file that is in the code window. |
|
2706
|
|
|
|
|
|
|
# |
|
2707
|
|
|
|
|
|
|
# $fname the 'new' file to view |
|
2708
|
|
|
|
|
|
|
# $line the line number we're at |
|
2709
|
|
|
|
|
|
|
# $brkPts any breakpoints that may have been set in this file |
|
2710
|
|
|
|
|
|
|
# |
|
2711
|
|
|
|
|
|
|
|
|
2712
|
|
|
|
|
|
|
use Carp ; |
|
2713
|
|
|
|
|
|
|
|
|
2714
|
|
|
|
|
|
|
sub set_file { |
|
2715
|
|
|
|
|
|
|
my ($self, $fname, $line) = @_ ; |
|
2716
|
|
|
|
|
|
|
my ($lineStr, $offset, $text, $i, @text, $noCode, $title) ; |
|
2717
|
|
|
|
|
|
|
my (@breakableTagList, @nonBreakableTagList) ; |
|
2718
|
|
|
|
|
|
|
|
|
2719
|
|
|
|
|
|
|
return unless $fname ; # we're getting an undef here on 'Restart...' |
|
2720
|
|
|
|
|
|
|
|
|
2721
|
|
|
|
|
|
|
local(*dbline) = $main::{'_<' . $fname}; |
|
2722
|
|
|
|
|
|
|
|
|
2723
|
|
|
|
|
|
|
# |
|
2724
|
|
|
|
|
|
|
# with the #! /usr/bin/perl -d:ptkdb at the header of the file |
|
2725
|
|
|
|
|
|
|
# we've found that with various combinations of other options the |
|
2726
|
|
|
|
|
|
|
# files haven't come in at the right offsets |
|
2727
|
|
|
|
|
|
|
# |
|
2728
|
|
|
|
|
|
|
$offset = 0 ; |
|
2729
|
|
|
|
|
|
|
$offset = 1 if $dbline[1] =~ /use\s+.*Devel::_?ptkdb/ ; |
|
2730
|
|
|
|
|
|
|
$self->{'line_offset'} = $offset ; |
|
2731
|
|
|
|
|
|
|
|
|
2732
|
|
|
|
|
|
|
$text = $self->{'text'} ; |
|
2733
|
|
|
|
|
|
|
|
|
2734
|
|
|
|
|
|
|
if( $fname eq $self->{current_file} ) { |
|
2735
|
|
|
|
|
|
|
$self->set_line($line) ; |
|
2736
|
|
|
|
|
|
|
return ; |
|
2737
|
|
|
|
|
|
|
} ; |
|
2738
|
|
|
|
|
|
|
|
|
2739
|
|
|
|
|
|
|
$title = $fname ; # removing the - messes up stashes on -e invocations |
|
2740
|
|
|
|
|
|
|
$title =~ s/^\-// ; # Tk does not like leadiing '-'s |
|
2741
|
|
|
|
|
|
|
$self->{main_window}->configure('-title' => $title) ; |
|
2742
|
|
|
|
|
|
|
|
|
2743
|
|
|
|
|
|
|
# Erase any existing text |
|
2744
|
|
|
|
|
|
|
|
|
2745
|
|
|
|
|
|
|
$text->delete('0.0','end') ; |
|
2746
|
|
|
|
|
|
|
|
|
2747
|
|
|
|
|
|
|
my $len = $Devel::ptkdb::linenumber_length ; |
|
2748
|
|
|
|
|
|
|
|
|
2749
|
|
|
|
|
|
|
# |
|
2750
|
|
|
|
|
|
|
# This is the tightest loop we have in the ptkdb code. |
|
2751
|
|
|
|
|
|
|
# It is here where performance is the most critical. |
|
2752
|
|
|
|
|
|
|
# The map block formats perl code for display. Since |
|
2753
|
|
|
|
|
|
|
# the file could be potentially large, we will try |
|
2754
|
|
|
|
|
|
|
# to make this loop as thin as possible. |
|
2755
|
|
|
|
|
|
|
# |
|
2756
|
|
|
|
|
|
|
# NOTE: For a new perl individual this may appear as |
|
2757
|
|
|
|
|
|
|
# if it was intentionally obfuscated. This is not |
|
2758
|
|
|
|
|
|
|
# not the case. The following code is the result |
|
2759
|
|
|
|
|
|
|
# of an intensive effort to optimize this code. |
|
2760
|
|
|
|
|
|
|
# Prior versions of this code were quite easier |
|
2761
|
|
|
|
|
|
|
# to read, but took 3 times longer. |
|
2762
|
|
|
|
|
|
|
# |
|
2763
|
|
|
|
|
|
|
|
|
2764
|
|
|
|
|
|
|
$lineStr = " " x 200 ; # pre-allocate space for $lineStr |
|
2765
|
|
|
|
|
|
|
$i = 1 ; |
|
2766
|
|
|
|
|
|
|
|
|
2767
|
|
|
|
|
|
|
local($^W) = 0 ; # spares us useless warnings under -w when checking $dbline[$_] != 0 |
|
2768
|
|
|
|
|
|
|
# |
|
2769
|
|
|
|
|
|
|
# The 'map' call will build list of 'string', 'tag' pairs |
|
2770
|
|
|
|
|
|
|
# that will become arguments to the 'insert' call. Passing |
|
2771
|
|
|
|
|
|
|
# the text to insert "all at once" rather than one insert->('end', 'string', 'tag') |
|
2772
|
|
|
|
|
|
|
# call at time provides a MASSIVE savings in execution time. |
|
2773
|
|
|
|
|
|
|
# |
|
2774
|
|
|
|
|
|
|
$noCode = ($#dbline - ($offset + 1)) < 0 ; |
|
2775
|
|
|
|
|
|
|
|
|
2776
|
|
|
|
|
|
|
$text->insert('end', map { |
|
2777
|
|
|
|
|
|
|
# |
|
2778
|
|
|
|
|
|
|
# build collections of tags representing |
|
2779
|
|
|
|
|
|
|
# the line numbers for breakable and |
|
2780
|
|
|
|
|
|
|
# non-breakable lines. We apply these |
|
2781
|
|
|
|
|
|
|
# tags after we've built the text |
|
2782
|
|
|
|
|
|
|
# |
|
2783
|
|
|
|
|
|
|
|
|
2784
|
|
|
|
|
|
|
($_ != 0 && push @breakableTagList, "$i.0", "$i.$len") || push @nonBreakableTagList, "$i.0", "$i.$len" ; |
|
2785
|
|
|
|
|
|
|
|
|
2786
|
|
|
|
|
|
|
$lineStr = sprintf($Devel::ptkdb::linenumber_format, $i++) . $_ ; # line number + text of the line |
|
2787
|
|
|
|
|
|
|
|
|
2788
|
|
|
|
|
|
|
substr $lineStr, -2, 1, '' if $isWin32 ; # removes the CR from win32 instances |
|
2789
|
|
|
|
|
|
|
|
|
2790
|
|
|
|
|
|
|
$lineStr .= "\n" unless /\n$/o ; # append a \n if there isn't one already |
|
2791
|
|
|
|
|
|
|
|
|
2792
|
|
|
|
|
|
|
($lineStr, 'code') ; # return value for block, a string,tag pair for text insert |
|
2793
|
|
|
|
|
|
|
|
|
2794
|
|
|
|
|
|
|
} @dbline[$offset+1 .. $#dbline] ) unless $noCode ; |
|
2795
|
|
|
|
|
|
|
|
|
2796
|
|
|
|
|
|
|
# |
|
2797
|
|
|
|
|
|
|
# Apply the tags that we've collected |
|
2798
|
|
|
|
|
|
|
# NOTE: it was attempted to incorporate these |
|
2799
|
|
|
|
|
|
|
# operations into the 'map' block above, but that |
|
2800
|
|
|
|
|
|
|
# actually degraded performance. |
|
2801
|
|
|
|
|
|
|
# |
|
2802
|
|
|
|
|
|
|
$text->tagAdd("breakableLine", @breakableTagList) if @breakableTagList ; # apply tag to line numbers where the lines are breakable |
|
2803
|
|
|
|
|
|
|
$text->tagAdd("nonbreakableLine", @nonBreakableTagList) if @nonBreakableTagList ; # apply tag to line numbers where the lines are not breakable. |
|
2804
|
|
|
|
|
|
|
|
|
2805
|
|
|
|
|
|
|
# |
|
2806
|
|
|
|
|
|
|
# Reinsert breakpoints (if info provided) |
|
2807
|
|
|
|
|
|
|
# |
|
2808
|
|
|
|
|
|
|
|
|
2809
|
|
|
|
|
|
|
$self->set_line($line) ; |
|
2810
|
|
|
|
|
|
|
$self->{current_file} = $fname ; |
|
2811
|
|
|
|
|
|
|
return $self->reinsertBreakpoints($fname) ; |
|
2812
|
|
|
|
|
|
|
} # end of set_file |
|
2813
|
|
|
|
|
|
|
|
|
2814
|
|
|
|
|
|
|
# |
|
2815
|
|
|
|
|
|
|
# Get the current line that the insert cursor is in |
|
2816
|
|
|
|
|
|
|
# |
|
2817
|
|
|
|
|
|
|
sub get_lineno { |
|
2818
|
|
|
|
|
|
|
my ($self) = @_ ; |
|
2819
|
|
|
|
|
|
|
my ($info) ; |
|
2820
|
|
|
|
|
|
|
|
|
2821
|
|
|
|
|
|
|
$info = $self->{'text'}->index('insert') ; # get the location for the insertion point |
|
2822
|
|
|
|
|
|
|
$info =~ s/\..*$/\.0/ ; |
|
2823
|
|
|
|
|
|
|
|
|
2824
|
|
|
|
|
|
|
return int $info ; |
|
2825
|
|
|
|
|
|
|
} # end of get_lineno |
|
2826
|
|
|
|
|
|
|
|
|
2827
|
|
|
|
|
|
|
sub DoGoto { |
|
2828
|
|
|
|
|
|
|
my ($self, $entry) = @_ ; |
|
2829
|
|
|
|
|
|
|
|
|
2830
|
|
|
|
|
|
|
my $txt = $entry->get() ; |
|
2831
|
|
|
|
|
|
|
|
|
2832
|
|
|
|
|
|
|
$txt =~ s/(\d*).*/$1/ ; # take the first blob of digits |
|
2833
|
|
|
|
|
|
|
if( $txt eq "" ) { |
|
2834
|
|
|
|
|
|
|
print "invalid text range\n" ; |
|
2835
|
|
|
|
|
|
|
return if $txt eq "" ; |
|
2836
|
|
|
|
|
|
|
} |
|
2837
|
|
|
|
|
|
|
|
|
2838
|
|
|
|
|
|
|
$self->{'text'}->see("$txt.0") ; |
|
2839
|
|
|
|
|
|
|
|
|
2840
|
|
|
|
|
|
|
$entry->selectionRange(0, 'end') if $entry->can('selectionRange') |
|
2841
|
|
|
|
|
|
|
|
|
2842
|
|
|
|
|
|
|
} # end of DoGoto |
|
2843
|
|
|
|
|
|
|
|
|
2844
|
|
|
|
|
|
|
sub GotoLine { |
|
2845
|
|
|
|
|
|
|
my ($self) = @_ ; |
|
2846
|
|
|
|
|
|
|
my ($topLevel) ; |
|
2847
|
|
|
|
|
|
|
|
|
2848
|
|
|
|
|
|
|
if( $self->{goto_window} ) { |
|
2849
|
|
|
|
|
|
|
$self->{goto_window}->raise() ; |
|
2850
|
|
|
|
|
|
|
$self->{goto_text}->focus() ; |
|
2851
|
|
|
|
|
|
|
return ; |
|
2852
|
|
|
|
|
|
|
} |
|
2853
|
|
|
|
|
|
|
|
|
2854
|
|
|
|
|
|
|
# |
|
2855
|
|
|
|
|
|
|
# Construct a dialog that has an |
|
2856
|
|
|
|
|
|
|
# entry field, okay and cancel buttons |
|
2857
|
|
|
|
|
|
|
# |
|
2858
|
|
|
|
|
|
|
my $okaySub = sub { $self->DoGoto($self->{'goto_text'}) } ; |
|
2859
|
|
|
|
|
|
|
|
|
2860
|
|
|
|
|
|
|
$topLevel = $self->{main_window}->Toplevel(-title => "Goto Line?", -overanchor => 'cursor') ; |
|
2861
|
|
|
|
|
|
|
|
|
2862
|
|
|
|
|
|
|
$self->{goto_text} = $topLevel->Entry()->pack(-side => 'top', -fill => 'both', -expand => 1) ; |
|
2863
|
|
|
|
|
|
|
|
|
2864
|
|
|
|
|
|
|
$self->{goto_text}->bind('', $okaySub) ; # make a CR do the same thing as pressing an okay |
|
2865
|
|
|
|
|
|
|
|
|
2866
|
|
|
|
|
|
|
$self->{goto_text}->focus() ; |
|
2867
|
|
|
|
|
|
|
|
|
2868
|
|
|
|
|
|
|
# Bind a double click on the mouse button to the same action |
|
2869
|
|
|
|
|
|
|
# as pressing the Okay button |
|
2870
|
|
|
|
|
|
|
|
|
2871
|
|
|
|
|
|
|
$topLevel->Button( -text => "Okay", -command => $okaySub, @Devel::ptkdb::button_font, |
|
2872
|
|
|
|
|
|
|
)->pack(-side => 'left', -fill => 'both', -expand => 1) ; |
|
2873
|
|
|
|
|
|
|
|
|
2874
|
|
|
|
|
|
|
# |
|
2875
|
|
|
|
|
|
|
# Subroutone called when the 'Dismiss' |
|
2876
|
|
|
|
|
|
|
# button is pushed. |
|
2877
|
|
|
|
|
|
|
# |
|
2878
|
|
|
|
|
|
|
my $dismissSub = sub { |
|
2879
|
|
|
|
|
|
|
delete $self->{goto_text} ; |
|
2880
|
|
|
|
|
|
|
destroy {$self->{goto_window}} ; |
|
2881
|
|
|
|
|
|
|
delete $self->{goto_window} ; # remove the entry from our hash so we won't |
|
2882
|
|
|
|
|
|
|
} ; |
|
2883
|
|
|
|
|
|
|
|
|
2884
|
|
|
|
|
|
|
$topLevel->Button( -text => "Dismiss", @Devel::ptkdb::button_font, |
|
2885
|
|
|
|
|
|
|
-command => $dismissSub )->pack(-side => 'left', -fill => 'both', -expand => 1) ; |
|
2886
|
|
|
|
|
|
|
|
|
2887
|
|
|
|
|
|
|
$topLevel->protocol('WM_DELETE_WINDOW', sub { destroy $topLevel ; } ) ; |
|
2888
|
|
|
|
|
|
|
|
|
2889
|
|
|
|
|
|
|
$self->{goto_window} = $topLevel ; |
|
2890
|
|
|
|
|
|
|
|
|
2891
|
|
|
|
|
|
|
} # end of GotoLine |
|
2892
|
|
|
|
|
|
|
|
|
2893
|
|
|
|
|
|
|
|
|
2894
|
|
|
|
|
|
|
# |
|
2895
|
|
|
|
|
|
|
# Subroutine called when the 'okay' button is pressed |
|
2896
|
|
|
|
|
|
|
# |
|
2897
|
|
|
|
|
|
|
sub FindSearch { |
|
2898
|
|
|
|
|
|
|
my ($self, $entry, $btn, $regExp) = @_ ; |
|
2899
|
|
|
|
|
|
|
my (@switches, $result) ; |
|
2900
|
|
|
|
|
|
|
my $txt = $entry->get() ; |
|
2901
|
|
|
|
|
|
|
|
|
2902
|
|
|
|
|
|
|
return if $txt eq "" ; |
|
2903
|
|
|
|
|
|
|
|
|
2904
|
|
|
|
|
|
|
push @switches, "-forward" if $self->{fwdOrBack} eq "forward" ; |
|
2905
|
|
|
|
|
|
|
push @switches, "-backward" if $self->{fwdOrBack} eq "backward" ; |
|
2906
|
|
|
|
|
|
|
|
|
2907
|
|
|
|
|
|
|
if( $regExp ) { |
|
2908
|
|
|
|
|
|
|
push @switches, "-regexp" ; |
|
2909
|
|
|
|
|
|
|
} |
|
2910
|
|
|
|
|
|
|
else { |
|
2911
|
|
|
|
|
|
|
push @switches, "-nocase" ; # if we're not doing regex we may as well do caseless search |
|
2912
|
|
|
|
|
|
|
} |
|
2913
|
|
|
|
|
|
|
|
|
2914
|
|
|
|
|
|
|
$result = $self->{'text'}->search(@switches, $txt, $self->{search_start}) ; |
|
2915
|
|
|
|
|
|
|
|
|
2916
|
|
|
|
|
|
|
# untag the previously found text |
|
2917
|
|
|
|
|
|
|
|
|
2918
|
|
|
|
|
|
|
$self->{'text'}->tagRemove('search_tag', @{$self->{search_tag}}) if defined $self->{search_tag} ; |
|
2919
|
|
|
|
|
|
|
|
|
2920
|
|
|
|
|
|
|
if( !$result || $result eq "" ) { |
|
2921
|
|
|
|
|
|
|
# No Text was found |
|
2922
|
|
|
|
|
|
|
$btn->flash() ; |
|
2923
|
|
|
|
|
|
|
$btn->bell() ; |
|
2924
|
|
|
|
|
|
|
|
|
2925
|
|
|
|
|
|
|
delete $self->{search_tag} ; |
|
2926
|
|
|
|
|
|
|
$self->{'search_start'} = "0.0" ; |
|
2927
|
|
|
|
|
|
|
} |
|
2928
|
|
|
|
|
|
|
else { # text found |
|
2929
|
|
|
|
|
|
|
$self->{'text'}->see($result) ; |
|
2930
|
|
|
|
|
|
|
# set the insertion of the text as well |
|
2931
|
|
|
|
|
|
|
$self->{'text'}->markSet('insert' => $result) ; |
|
2932
|
|
|
|
|
|
|
my $len = length $txt ; |
|
2933
|
|
|
|
|
|
|
|
|
2934
|
|
|
|
|
|
|
if( $self->{fwdOrBack} ) { |
|
2935
|
|
|
|
|
|
|
$self->{search_start} = "$result +$len chars" ; |
|
2936
|
|
|
|
|
|
|
$self->{search_tag} = [ $result, $self->{search_start} ] ; |
|
2937
|
|
|
|
|
|
|
} |
|
2938
|
|
|
|
|
|
|
else { |
|
2939
|
|
|
|
|
|
|
# backwards search |
|
2940
|
|
|
|
|
|
|
$self->{search_start} = "$result -$len chars" ; |
|
2941
|
|
|
|
|
|
|
$self->{search_tag} = [ $result, "$result +$len chars" ] ; |
|
2942
|
|
|
|
|
|
|
} |
|
2943
|
|
|
|
|
|
|
|
|
2944
|
|
|
|
|
|
|
# tag the newly found text |
|
2945
|
|
|
|
|
|
|
|
|
2946
|
|
|
|
|
|
|
$self->{'text'}->tagAdd('search_tag', @{$self->{search_tag}}) ; |
|
2947
|
|
|
|
|
|
|
} # end of text found |
|
2948
|
|
|
|
|
|
|
|
|
2949
|
|
|
|
|
|
|
$entry->selectionRange(0, 'end') if $entry->can('selectionRange') ; |
|
2950
|
|
|
|
|
|
|
|
|
2951
|
|
|
|
|
|
|
} # end of FindSearch |
|
2952
|
|
|
|
|
|
|
|
|
2953
|
|
|
|
|
|
|
|
|
2954
|
|
|
|
|
|
|
# |
|
2955
|
|
|
|
|
|
|
# Support for the Find Text... Menu command |
|
2956
|
|
|
|
|
|
|
# |
|
2957
|
|
|
|
|
|
|
sub FindText { |
|
2958
|
|
|
|
|
|
|
my ($self) = @_ ; |
|
2959
|
|
|
|
|
|
|
my ($top, $entry, $rad1, $rad2, $chk, $regExp, $frm, $okayBtn) ; |
|
2960
|
|
|
|
|
|
|
|
|
2961
|
|
|
|
|
|
|
# |
|
2962
|
|
|
|
|
|
|
# if we already have the Find Text Window |
|
2963
|
|
|
|
|
|
|
# open don't bother openning another, bring |
|
2964
|
|
|
|
|
|
|
# the existing one to the front. |
|
2965
|
|
|
|
|
|
|
# |
|
2966
|
|
|
|
|
|
|
if( $self->{find_window} ) { |
|
2967
|
|
|
|
|
|
|
$self->{find_window}->raise() ; |
|
2968
|
|
|
|
|
|
|
$self->{find_text}->focus() ; |
|
2969
|
|
|
|
|
|
|
return ; |
|
2970
|
|
|
|
|
|
|
} |
|
2971
|
|
|
|
|
|
|
|
|
2972
|
|
|
|
|
|
|
$self->{search_start} = $self->{'text'}->index('insert') if( $self->{search_start} eq "" ) ; |
|
2973
|
|
|
|
|
|
|
|
|
2974
|
|
|
|
|
|
|
# |
|
2975
|
|
|
|
|
|
|
# Subroutine called when the 'Dismiss' button |
|
2976
|
|
|
|
|
|
|
# is pushed. |
|
2977
|
|
|
|
|
|
|
# |
|
2978
|
|
|
|
|
|
|
my $dismissSub = sub { |
|
2979
|
|
|
|
|
|
|
$self->{'text'}->tagRemove('search_tag', @{$self->{search_tag}}) if defined $self->{search_tag} ; |
|
2980
|
|
|
|
|
|
|
$self->{search_start} = "" ; |
|
2981
|
|
|
|
|
|
|
destroy {$self->{find_window}} ; |
|
2982
|
|
|
|
|
|
|
delete $self->{search_tag} ; |
|
2983
|
|
|
|
|
|
|
delete $self->{find_window} ; |
|
2984
|
|
|
|
|
|
|
} ; |
|
2985
|
|
|
|
|
|
|
|
|
2986
|
|
|
|
|
|
|
# |
|
2987
|
|
|
|
|
|
|
# Construct a dialog that has an entry field, forward, backward, regex option, okay and cancel buttons |
|
2988
|
|
|
|
|
|
|
# |
|
2989
|
|
|
|
|
|
|
$top = $self->{main_window}->Toplevel(-title => "Find Text?") ; |
|
2990
|
|
|
|
|
|
|
|
|
2991
|
|
|
|
|
|
|
$self->{find_text} = $top->Entry()->pack(-side => 'top', -fill => 'both', -expand => 1) ; |
|
2992
|
|
|
|
|
|
|
|
|
2993
|
|
|
|
|
|
|
|
|
2994
|
|
|
|
|
|
|
$frm = $top->Frame()->pack(-side => 'top', -fill => 'both', -expand => 1) ; |
|
2995
|
|
|
|
|
|
|
|
|
2996
|
|
|
|
|
|
|
$self->{fwdOrBack} = 'forward' ; |
|
2997
|
|
|
|
|
|
|
$rad1 = $frm->Radiobutton(-text => "Forward", -value => 1, -variable => \$self->{fwdOrBack}) ; |
|
2998
|
|
|
|
|
|
|
$rad1->pack(-side => 'left', -fill => 'both', -expand => 1) ; |
|
2999
|
|
|
|
|
|
|
$rad2 = $frm->Radiobutton(-text => "Backward", -value => 0, -variable => \$self->{fwdOrBack}) ; |
|
3000
|
|
|
|
|
|
|
$rad2->pack(-side => 'left', -fill => 'both', -expand => 1) ; |
|
3001
|
|
|
|
|
|
|
|
|
3002
|
|
|
|
|
|
|
$regExp = 0 ; |
|
3003
|
|
|
|
|
|
|
$chk = $frm->Checkbutton(-text => "RegExp", -variable => \$regExp) ; |
|
3004
|
|
|
|
|
|
|
$chk->pack(-side => 'left', -fill => 'both', -expand => 1) ; |
|
3005
|
|
|
|
|
|
|
|
|
3006
|
|
|
|
|
|
|
# Okay and cancel buttons |
|
3007
|
|
|
|
|
|
|
|
|
3008
|
|
|
|
|
|
|
# Bind a double click on the mouse button to the same action |
|
3009
|
|
|
|
|
|
|
# as pressing the Okay button |
|
3010
|
|
|
|
|
|
|
|
|
3011
|
|
|
|
|
|
|
$okayBtn = $top->Button( -text => "Okay", -command => sub { $self->FindSearch($self->{find_text}, $okayBtn, $regExp) ; }, |
|
3012
|
|
|
|
|
|
|
@Devel::ptkdb::button_font, |
|
3013
|
|
|
|
|
|
|
)->pack(-side => 'left', -fill => 'both', -expand => 1) ; |
|
3014
|
|
|
|
|
|
|
|
|
3015
|
|
|
|
|
|
|
$self->{find_text}->bind('', sub { $self->FindSearch($self->{find_text}, $okayBtn, $regExp) ; }) ; |
|
3016
|
|
|
|
|
|
|
|
|
3017
|
|
|
|
|
|
|
$top->Button( -text => "Dismiss", @Devel::ptkdb::button_font, |
|
3018
|
|
|
|
|
|
|
-command => $dismissSub)->pack(-side => 'left', -fill => 'both', -expand => 1) ; |
|
3019
|
|
|
|
|
|
|
|
|
3020
|
|
|
|
|
|
|
$top->protocol('WM_DELETE_WINDOW', $dismissSub) ; |
|
3021
|
|
|
|
|
|
|
|
|
3022
|
|
|
|
|
|
|
$self->{find_text}->focus() ; |
|
3023
|
|
|
|
|
|
|
|
|
3024
|
|
|
|
|
|
|
$self->{find_window} = $top ; |
|
3025
|
|
|
|
|
|
|
|
|
3026
|
|
|
|
|
|
|
} # end of FindText |
|
3027
|
|
|
|
|
|
|
|
|
3028
|
|
|
|
|
|
|
sub main_loop { |
|
3029
|
|
|
|
|
|
|
my ($self) = @_ ; |
|
3030
|
|
|
|
|
|
|
my ($evt, $str, $result) ; |
|
3031
|
|
|
|
|
|
|
my $i = 0; |
|
3032
|
|
|
|
|
|
|
SWITCH: for ($self->{'event'} = 'null' ; ; $self->{'event'} = undef ) { |
|
3033
|
|
|
|
|
|
|
|
|
3034
|
|
|
|
|
|
|
Tk::DoOneEvent(0); |
|
3035
|
|
|
|
|
|
|
next unless $self->{'event'} ; |
|
3036
|
|
|
|
|
|
|
|
|
3037
|
|
|
|
|
|
|
$evt = $self->{'event'} ; |
|
3038
|
|
|
|
|
|
|
$evt =~ /step/o && do { last SWITCH ; } ; |
|
3039
|
|
|
|
|
|
|
$evt =~ /null/o && do { next SWITCH ; } ; |
|
3040
|
|
|
|
|
|
|
$evt =~ /run/o && do { last SWITCH ; } ; |
|
3041
|
|
|
|
|
|
|
$evt =~ /quit/o && do { $self->DoQuit ; } ; |
|
3042
|
|
|
|
|
|
|
$evt =~ /expr/o && do { return $evt ; } ; # adds an expression to our expression window |
|
3043
|
|
|
|
|
|
|
$evt =~ /qexpr/o && do { return $evt ; } ; # does a 'quick' expression |
|
3044
|
|
|
|
|
|
|
$evt =~ /update/o && do { return $evt ; } ; # forces an update on our expression window |
|
3045
|
|
|
|
|
|
|
$evt =~ /reeval/o && do { return $evt ; } ; # updated the open expression eval window |
|
3046
|
|
|
|
|
|
|
$evt =~ /balloon_eval/ && do { return $evt } ; |
|
3047
|
|
|
|
|
|
|
} # end of switch block |
|
3048
|
|
|
|
|
|
|
return $evt ; |
|
3049
|
|
|
|
|
|
|
} # end of main_loop |
|
3050
|
|
|
|
|
|
|
|
|
3051
|
|
|
|
|
|
|
# |
|
3052
|
|
|
|
|
|
|
# $subStackRef A reference to the current subroutine stack |
|
3053
|
|
|
|
|
|
|
# |
|
3054
|
|
|
|
|
|
|
|
|
3055
|
|
|
|
|
|
|
sub goto_sub_from_stack { |
|
3056
|
|
|
|
|
|
|
my ($self, $f, $lineno) = @_ ; |
|
3057
|
|
|
|
|
|
|
$self->set_file($f, $lineno) ; |
|
3058
|
|
|
|
|
|
|
} # end of goto_sub_from_stack ; |
|
3059
|
|
|
|
|
|
|
|
|
3060
|
|
|
|
|
|
|
sub refresh_stack_menu { |
|
3061
|
|
|
|
|
|
|
my ($self) = @_ ; |
|
3062
|
|
|
|
|
|
|
my ($str, $name, $i, $sub_offset, $subStack) ; |
|
3063
|
|
|
|
|
|
|
|
|
3064
|
|
|
|
|
|
|
# |
|
3065
|
|
|
|
|
|
|
# CAUTION: In the effort to 'rationalize' the code |
|
3066
|
|
|
|
|
|
|
# are moving some of this function down from DB::DB |
|
3067
|
|
|
|
|
|
|
# to here. $sub_offset represents how far 'down' |
|
3068
|
|
|
|
|
|
|
# we are from DB::DB. The $DB::subroutine_depth is |
|
3069
|
|
|
|
|
|
|
# tracked in such a way that while we are 'in' the debugger |
|
3070
|
|
|
|
|
|
|
# it will not be incremented, and thus represents the stack depth |
|
3071
|
|
|
|
|
|
|
# of the target program. |
|
3072
|
|
|
|
|
|
|
# |
|
3073
|
|
|
|
|
|
|
$sub_offset = 1 ; |
|
3074
|
|
|
|
|
|
|
$subStack = [] ; |
|
3075
|
|
|
|
|
|
|
|
|
3076
|
|
|
|
|
|
|
# clear existing entries |
|
3077
|
|
|
|
|
|
|
|
|
3078
|
|
|
|
|
|
|
for( $i = 0 ; $i <= $DB::subroutine_depth ; $i++ ) { |
|
3079
|
|
|
|
|
|
|
my ($package, $filename, $line, $subName) = caller $i+$sub_offset ; |
|
3080
|
|
|
|
|
|
|
last if !$subName ; |
|
3081
|
|
|
|
|
|
|
push @$subStack, { 'name' => $subName, 'pck' => $package, 'filename' => $filename, 'line' => $line } ; |
|
3082
|
|
|
|
|
|
|
} |
|
3083
|
|
|
|
|
|
|
|
|
3084
|
|
|
|
|
|
|
$self->{stack_menu}->menu->delete(0, 'last') ; # delete existing menu items |
|
3085
|
|
|
|
|
|
|
|
|
3086
|
|
|
|
|
|
|
for( $i = 0 ; $subStack->[$i] ; $i++ ) { |
|
3087
|
|
|
|
|
|
|
|
|
3088
|
|
|
|
|
|
|
$str = defined $subStack->[$i+1] ? "$subStack->[$i+1]->{name}" : "MAIN" ; |
|
3089
|
|
|
|
|
|
|
|
|
3090
|
|
|
|
|
|
|
my ($f, $line) = ($subStack->[$i]->{filename}, $subStack->[$i]->{line}) ; # make copies of the values for use in 'sub' |
|
3091
|
|
|
|
|
|
|
$self->{stack_menu}->command(-label => $str, -command => sub { $self->goto_sub_from_stack($f, $line) ; } ) ; |
|
3092
|
|
|
|
|
|
|
} |
|
3093
|
|
|
|
|
|
|
} # end of refresh_stack_menu |
|
3094
|
|
|
|
|
|
|
|
|
3095
|
|
|
|
|
|
|
no strict ; |
|
3096
|
|
|
|
|
|
|
|
|
3097
|
|
|
|
|
|
|
sub get_state { |
|
3098
|
|
|
|
|
|
|
my ($self, $fname) = @_ ; |
|
3099
|
|
|
|
|
|
|
my ($val) ; |
|
3100
|
|
|
|
|
|
|
local($files, $expr_list, $eval_saved_text, $main_win_geometry) ; |
|
3101
|
|
|
|
|
|
|
|
|
3102
|
|
|
|
|
|
|
do "$fname" ; |
|
3103
|
|
|
|
|
|
|
|
|
3104
|
|
|
|
|
|
|
if( $@ ) { |
|
3105
|
|
|
|
|
|
|
$self->DoAlert($@) ; |
|
3106
|
|
|
|
|
|
|
return ( undef ) x 4 ; # return a list of 4 undefined values |
|
3107
|
|
|
|
|
|
|
} |
|
3108
|
|
|
|
|
|
|
|
|
3109
|
|
|
|
|
|
|
return ($files, $expr_list, $eval_saved_text, $main_win_geometry) ; |
|
3110
|
|
|
|
|
|
|
} # end of get_state |
|
3111
|
|
|
|
|
|
|
|
|
3112
|
|
|
|
|
|
|
use strict ; |
|
3113
|
|
|
|
|
|
|
|
|
3114
|
|
|
|
|
|
|
sub restoreStateFile { |
|
3115
|
|
|
|
|
|
|
my ($self, $fname) = @_ ; |
|
3116
|
|
|
|
|
|
|
local(*F) ; |
|
3117
|
|
|
|
|
|
|
my ($saveCurFile, $s, @n, $n) ; |
|
3118
|
|
|
|
|
|
|
|
|
3119
|
|
|
|
|
|
|
if (!(-e $fname && -r $fname)) { |
|
3120
|
|
|
|
|
|
|
$self->DoAlert("$fname does not exist") ; |
|
3121
|
|
|
|
|
|
|
return ; |
|
3122
|
|
|
|
|
|
|
} |
|
3123
|
|
|
|
|
|
|
|
|
3124
|
|
|
|
|
|
|
my ($files, $expr_list, $eval_saved_text, $main_win_geometry) = $self->get_state($fname) ; |
|
3125
|
|
|
|
|
|
|
my ($f, $brks) ; |
|
3126
|
|
|
|
|
|
|
|
|
3127
|
|
|
|
|
|
|
return unless defined $files || defined $expr_list ; |
|
3128
|
|
|
|
|
|
|
|
|
3129
|
|
|
|
|
|
|
&DB::restore_breakpoints_from_save($files) ; |
|
3130
|
|
|
|
|
|
|
|
|
3131
|
|
|
|
|
|
|
# |
|
3132
|
|
|
|
|
|
|
# This should force the breakpoints to be restored |
|
3133
|
|
|
|
|
|
|
# |
|
3134
|
|
|
|
|
|
|
$saveCurFile = $self->{current_file} ; |
|
3135
|
|
|
|
|
|
|
|
|
3136
|
|
|
|
|
|
|
@$self{ 'current_file', 'expr_list', 'eval_saved_text' } = |
|
3137
|
|
|
|
|
|
|
( "" , $expr_list, $eval_saved_text) ; |
|
3138
|
|
|
|
|
|
|
|
|
3139
|
|
|
|
|
|
|
$self->set_file($saveCurFile, $self->{current_line}) ; |
|
3140
|
|
|
|
|
|
|
|
|
3141
|
|
|
|
|
|
|
$self->{'event'} = 'update' ; |
|
3142
|
|
|
|
|
|
|
|
|
3143
|
|
|
|
|
|
|
if ( $main_win_geometry && $self->{'main_window'} ) { |
|
3144
|
|
|
|
|
|
|
# restore the height and width of the window |
|
3145
|
|
|
|
|
|
|
$self->{main_window}->geometry( $main_win_geometry ) ; |
|
3146
|
|
|
|
|
|
|
} |
|
3147
|
|
|
|
|
|
|
} # end of retstoreState |
|
3148
|
|
|
|
|
|
|
|
|
3149
|
|
|
|
|
|
|
sub updateEvalWindow { |
|
3150
|
|
|
|
|
|
|
my ($self, @result) = @_ ; |
|
3151
|
|
|
|
|
|
|
my ($leng, $str, $d) ; |
|
3152
|
|
|
|
|
|
|
|
|
3153
|
|
|
|
|
|
|
$leng = 0 ; |
|
3154
|
|
|
|
|
|
|
for( @result ) { |
|
3155
|
|
|
|
|
|
|
if( $self->{hexdump_evals} ) { |
|
3156
|
|
|
|
|
|
|
# eventually put hex dumper code in here |
|
3157
|
|
|
|
|
|
|
|
|
3158
|
|
|
|
|
|
|
$self->{eval_results}->insert('end', hexDump($_)) ; |
|
3159
|
|
|
|
|
|
|
|
|
3160
|
|
|
|
|
|
|
} |
|
3161
|
|
|
|
|
|
|
elsif( !$Devel::ptkdb::DataDumperAvailable || !$Devel::ptkdb::useDataDumperForEval ) { |
|
3162
|
|
|
|
|
|
|
$str = "$_\n" ; |
|
3163
|
|
|
|
|
|
|
} |
|
3164
|
|
|
|
|
|
|
else { |
|
3165
|
|
|
|
|
|
|
$d = Data::Dumper->new([ $_ ]) ; |
|
3166
|
|
|
|
|
|
|
$d->Indent($Devel::ptkdb::eval_dump_indent) ; |
|
3167
|
|
|
|
|
|
|
$d->Terse(1) ; |
|
3168
|
|
|
|
|
|
|
if( Data::Dumper->can('Dumpxs') ) { |
|
3169
|
|
|
|
|
|
|
$str = $d->Dumpxs( $_ ) ; |
|
3170
|
|
|
|
|
|
|
} |
|
3171
|
|
|
|
|
|
|
else { |
|
3172
|
|
|
|
|
|
|
$str = $d->Dump( $_ ) ; |
|
3173
|
|
|
|
|
|
|
} |
|
3174
|
|
|
|
|
|
|
} |
|
3175
|
|
|
|
|
|
|
$leng += length $str ; |
|
3176
|
|
|
|
|
|
|
$self->{eval_results}->insert('end', $str) ; |
|
3177
|
|
|
|
|
|
|
} |
|
3178
|
|
|
|
|
|
|
} # end of updateEvalWindow |
|
3179
|
|
|
|
|
|
|
|
|
3180
|
|
|
|
|
|
|
|
|
3181
|
|
|
|
|
|
|
## |
|
3182
|
|
|
|
|
|
|
## converts non printable chars to '.' for a string |
|
3183
|
|
|
|
|
|
|
## |
|
3184
|
|
|
|
|
|
|
sub printablestr { |
|
3185
|
|
|
|
|
|
|
return join "", map { (ord($_) >= 32 && ord($_) < 127) ? $_ : '.' } split //, $_[0] ; |
|
3186
|
|
|
|
|
|
|
} |
|
3187
|
|
|
|
|
|
|
|
|
3188
|
|
|
|
|
|
|
## |
|
3189
|
|
|
|
|
|
|
## hex dump utility function |
|
3190
|
|
|
|
|
|
|
## |
|
3191
|
|
|
|
|
|
|
sub hexDump { |
|
3192
|
|
|
|
|
|
|
my(@retList) ; |
|
3193
|
|
|
|
|
|
|
my($width) = 8 ; |
|
3194
|
|
|
|
|
|
|
my($offset) ; |
|
3195
|
|
|
|
|
|
|
my($len, $fmt, $n, @elems) ; |
|
3196
|
|
|
|
|
|
|
|
|
3197
|
|
|
|
|
|
|
for( @_ ) { |
|
3198
|
|
|
|
|
|
|
my($str) ; |
|
3199
|
|
|
|
|
|
|
$len = length $_ ; |
|
3200
|
|
|
|
|
|
|
|
|
3201
|
|
|
|
|
|
|
while($len) { |
|
3202
|
|
|
|
|
|
|
$n = $len >= $width ? $width : $len ; |
|
3203
|
|
|
|
|
|
|
|
|
3204
|
|
|
|
|
|
|
$fmt = "\n%04X " . ("%02X " x $n ) . ( ' ' x ($width - $n) ) . " %s" ; |
|
3205
|
|
|
|
|
|
|
@elems = map ord, split //, (substr $_, $offset, $n) ; |
|
3206
|
|
|
|
|
|
|
$str .= sprintf($fmt, $offset, @elems, printablestr(substr $_, $offset, $n)) ; |
|
3207
|
|
|
|
|
|
|
$offset += $width ; |
|
3208
|
|
|
|
|
|
|
|
|
3209
|
|
|
|
|
|
|
$len -= $n ; |
|
3210
|
|
|
|
|
|
|
} # while |
|
3211
|
|
|
|
|
|
|
|
|
3212
|
|
|
|
|
|
|
push @retList, $str ; |
|
3213
|
|
|
|
|
|
|
} # for |
|
3214
|
|
|
|
|
|
|
|
|
3215
|
|
|
|
|
|
|
return $retList[0] unless wantarray ; |
|
3216
|
|
|
|
|
|
|
return @retList ; |
|
3217
|
|
|
|
|
|
|
} # end of hd |
|
3218
|
|
|
|
|
|
|
|
|
3219
|
|
|
|
|
|
|
|
|
3220
|
|
|
|
|
|
|
sub setupEvalWindow { |
|
3221
|
|
|
|
|
|
|
my($self) = @_ ; |
|
3222
|
|
|
|
|
|
|
my($top, $dismissSub) ; |
|
3223
|
|
|
|
|
|
|
my $f ; |
|
3224
|
|
|
|
|
|
|
$self->{eval_window}->focus(), return if exists $self->{eval_window} ; # already running this window? |
|
3225
|
|
|
|
|
|
|
|
|
3226
|
|
|
|
|
|
|
$top = $self->{main_window}->Toplevel(-title => "Evaluate Expressions...") ; |
|
3227
|
|
|
|
|
|
|
$self->{eval_window} = $top ; |
|
3228
|
|
|
|
|
|
|
$self->{eval_text} = $top->Scrolled('TextUndo', |
|
3229
|
|
|
|
|
|
|
@Devel::ptkdb::scrollbar_cfg, |
|
3230
|
|
|
|
|
|
|
@Devel::ptkdb::eval_text_font, |
|
3231
|
|
|
|
|
|
|
width => 50, |
|
3232
|
|
|
|
|
|
|
height => 10, |
|
3233
|
|
|
|
|
|
|
-wrap => "none", |
|
3234
|
|
|
|
|
|
|
)->packAdjust(-side => 'top', -fill => 'both', -expand => 1) ; |
|
3235
|
|
|
|
|
|
|
|
|
3236
|
|
|
|
|
|
|
$self->{eval_text}->insert('end', $self->{eval_saved_text}) if exists $self->{eval_saved_text} && defined $self->{eval_saved_text} ; |
|
3237
|
|
|
|
|
|
|
|
|
3238
|
|
|
|
|
|
|
$top->Label(-text, "Results:")->pack(-side => 'top', -fill => 'both', -expand => 'n') ; |
|
3239
|
|
|
|
|
|
|
|
|
3240
|
|
|
|
|
|
|
$self->{eval_results} = $top->Scrolled('Text', |
|
3241
|
|
|
|
|
|
|
@Devel::ptkdb::scrollbar_cfg, |
|
3242
|
|
|
|
|
|
|
width => 50, |
|
3243
|
|
|
|
|
|
|
height => 10, |
|
3244
|
|
|
|
|
|
|
-wrap => "none", |
|
3245
|
|
|
|
|
|
|
@Devel::ptkdb::eval_text_font |
|
3246
|
|
|
|
|
|
|
)->pack(-side => 'top', -fill => 'both', -expand => 1) ; |
|
3247
|
|
|
|
|
|
|
|
|
3248
|
|
|
|
|
|
|
my $btn = $top->Button(-text => 'Eval...', -command => sub { $DB::window->{event} = 'reeval' ; } |
|
3249
|
|
|
|
|
|
|
)->pack(-side => 'left', -fill => 'x', -expand => 1) ; |
|
3250
|
|
|
|
|
|
|
|
|
3251
|
|
|
|
|
|
|
$dismissSub = sub { |
|
3252
|
|
|
|
|
|
|
$self->{eval_saved_text} = $self->{eval_text}->get('0.0', 'end') ; |
|
3253
|
|
|
|
|
|
|
$self->{eval_window}->destroy ; |
|
3254
|
|
|
|
|
|
|
delete $self->{eval_window} ; |
|
3255
|
|
|
|
|
|
|
} ; |
|
3256
|
|
|
|
|
|
|
|
|
3257
|
|
|
|
|
|
|
$top->protocol('WM_DELETE_WINDOW', $dismissSub ) ; |
|
3258
|
|
|
|
|
|
|
|
|
3259
|
|
|
|
|
|
|
$top->Button(-text => 'Clear Eval', -command => sub { $self->{eval_text}->delete('0.0', 'end') } |
|
3260
|
|
|
|
|
|
|
)->pack(-side => 'left', -fill => 'x', -expand => 1) ; |
|
3261
|
|
|
|
|
|
|
|
|
3262
|
|
|
|
|
|
|
$top->Button(-text => 'Clear Results', -command => sub { $self->{eval_results}->delete('0.0', 'end') } |
|
3263
|
|
|
|
|
|
|
)->pack(-side => 'left', -fill => 'x', -expand => 1) ; |
|
3264
|
|
|
|
|
|
|
|
|
3265
|
|
|
|
|
|
|
$top->Button(-text => 'Dismiss', -command => $dismissSub)->pack(-side => 'left', -fill => 'x', -expand => 1) ; |
|
3266
|
|
|
|
|
|
|
$top->Checkbutton(-text => 'Hex', -variable => \$self->{hexdump_evals})->pack(-side => 'left') ; |
|
3267
|
|
|
|
|
|
|
|
|
3268
|
|
|
|
|
|
|
} # end of setupEvalWindow ; |
|
3269
|
|
|
|
|
|
|
|
|
3270
|
|
|
|
|
|
|
sub filterBreakPts { |
|
3271
|
|
|
|
|
|
|
my ($breakPtsListRef, $fname) = @_ ; |
|
3272
|
|
|
|
|
|
|
my $dbline = $main::{'_<' . $fname}; # breakable lines |
|
3273
|
|
|
|
|
|
|
local($^W) = 0 ; |
|
3274
|
|
|
|
|
|
|
# |
|
3275
|
|
|
|
|
|
|
# Go through the list of breaks and take out any that |
|
3276
|
|
|
|
|
|
|
# are no longer breakable |
|
3277
|
|
|
|
|
|
|
# |
|
3278
|
|
|
|
|
|
|
|
|
3279
|
|
|
|
|
|
|
for( @$breakPtsListRef ) { |
|
3280
|
|
|
|
|
|
|
next unless defined $_ ; |
|
3281
|
|
|
|
|
|
|
|
|
3282
|
|
|
|
|
|
|
next if $dbline->[$_->{'line'}] != 0 ; # still breakable |
|
3283
|
|
|
|
|
|
|
|
|
3284
|
|
|
|
|
|
|
$_ = undef ; |
|
3285
|
|
|
|
|
|
|
} |
|
3286
|
|
|
|
|
|
|
} # end of filterBreakPts |
|
3287
|
|
|
|
|
|
|
|
|
3288
|
|
|
|
|
|
|
sub DoAbout { |
|
3289
|
|
|
|
|
|
|
my $self = shift ; |
|
3290
|
|
|
|
|
|
|
my $str = "ptkdb $DB::VERSION\nCopyright 1998,2003 by Andrew E. Page\nFeedback to aepage\@users.sourceforge.net\n\n" ; |
|
3291
|
|
|
|
|
|
|
my $threadString = "" ; |
|
3292
|
|
|
|
|
|
|
|
|
3293
|
|
|
|
|
|
|
$threadString = "Threads Available" if $Config::Config{usethreads} ; |
|
3294
|
|
|
|
|
|
|
$threadString = " Thread Debugging Enabled" if $DB::usethreads ; |
|
3295
|
|
|
|
|
|
|
|
|
3296
|
|
|
|
|
|
|
$str .= <<"__STR__" ; |
|
3297
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify |
|
3298
|
|
|
|
|
|
|
it under the terms of either: |
|
3299
|
|
|
|
|
|
|
|
|
3300
|
|
|
|
|
|
|
a) the GNU General Public License as published by the Free |
|
3301
|
|
|
|
|
|
|
Software Foundation; either version 1, or (at your option) any |
|
3302
|
|
|
|
|
|
|
later version, or |
|
3303
|
|
|
|
|
|
|
|
|
3304
|
|
|
|
|
|
|
b) the "Artistic License" which comes with this Kit. |
|
3305
|
|
|
|
|
|
|
|
|
3306
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful, |
|
3307
|
|
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
3308
|
|
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either |
|
3309
|
|
|
|
|
|
|
the GNU General Public License or the Artistic License for more details. |
|
3310
|
|
|
|
|
|
|
|
|
3311
|
|
|
|
|
|
|
OS $^O |
|
3312
|
|
|
|
|
|
|
Tk Version $Tk::VERSION |
|
3313
|
|
|
|
|
|
|
Perl Version $] |
|
3314
|
|
|
|
|
|
|
Data::Dumper Version $Data::Dumper::VERSION |
|
3315
|
|
|
|
|
|
|
$threadString |
|
3316
|
|
|
|
|
|
|
__STR__ |
|
3317
|
|
|
|
|
|
|
|
|
3318
|
|
|
|
|
|
|
$self->DoAlert($str, "About ptkdb") ; |
|
3319
|
|
|
|
|
|
|
} # end of DoAbout |
|
3320
|
|
|
|
|
|
|
|
|
3321
|
|
|
|
|
|
|
# |
|
3322
|
|
|
|
|
|
|
# return 1 if succesfully set, |
|
3323
|
|
|
|
|
|
|
# return 0 if otherwise |
|
3324
|
|
|
|
|
|
|
# |
|
3325
|
|
|
|
|
|
|
sub SetBreakPoint { |
|
3326
|
|
|
|
|
|
|
my ($self, $isTemp) = @_ ; |
|
3327
|
|
|
|
|
|
|
my $dbw = $DB::window ; |
|
3328
|
|
|
|
|
|
|
my $lineno = $dbw->get_lineno() ; |
|
3329
|
|
|
|
|
|
|
my $expr = $dbw->clear_entry_text() ; |
|
3330
|
|
|
|
|
|
|
local($^W) = 0 ; |
|
3331
|
|
|
|
|
|
|
|
|
3332
|
|
|
|
|
|
|
if( !&DB::checkdbline($DB::window->{current_file}, $lineno + $self->{'line_offset'}) ) { |
|
3333
|
|
|
|
|
|
|
$dbw->DoAlert("line $lineno in $DB::window->{current_file} is not breakable") ; |
|
3334
|
|
|
|
|
|
|
return 0 ; |
|
3335
|
|
|
|
|
|
|
} |
|
3336
|
|
|
|
|
|
|
|
|
3337
|
|
|
|
|
|
|
if( !$isTemp ) { |
|
3338
|
|
|
|
|
|
|
$dbw->insertBreakpoint($DB::window->{current_file}, $lineno, 1, $expr) ; |
|
3339
|
|
|
|
|
|
|
return 1 ; |
|
3340
|
|
|
|
|
|
|
} |
|
3341
|
|
|
|
|
|
|
else { |
|
3342
|
|
|
|
|
|
|
$dbw->insertTempBreakpoint($DB::window->{current_file}, $lineno) ; |
|
3343
|
|
|
|
|
|
|
return 1 ; |
|
3344
|
|
|
|
|
|
|
} |
|
3345
|
|
|
|
|
|
|
|
|
3346
|
|
|
|
|
|
|
return 0 ; |
|
3347
|
|
|
|
|
|
|
} # end of SetBreakPoint |
|
3348
|
|
|
|
|
|
|
|
|
3349
|
|
|
|
|
|
|
sub UnsetBreakPoint { |
|
3350
|
|
|
|
|
|
|
my ($self) = @_ ; |
|
3351
|
|
|
|
|
|
|
my $lineno = $self->get_lineno() ; |
|
3352
|
|
|
|
|
|
|
|
|
3353
|
|
|
|
|
|
|
$self->removeBreakpoint($DB::window->{current_file}, $lineno) ; |
|
3354
|
|
|
|
|
|
|
} # end of UnsetBreakPoint |
|
3355
|
|
|
|
|
|
|
|
|
3356
|
|
|
|
|
|
|
sub balloon_post { |
|
3357
|
|
|
|
|
|
|
my $self = $DB::window ; |
|
3358
|
|
|
|
|
|
|
my $txt = $DB::window->{'text'} ; |
|
3359
|
|
|
|
|
|
|
|
|
3360
|
|
|
|
|
|
|
return 0 if ($self->{'expr_ballon_msg'} eq "") || ($self->{'balloon_expr'} eq "") ; # don't post for an empty string |
|
3361
|
|
|
|
|
|
|
|
|
3362
|
|
|
|
|
|
|
return $self->{'balloon_coord'} ; |
|
3363
|
|
|
|
|
|
|
} |
|
3364
|
|
|
|
|
|
|
|
|
3365
|
|
|
|
|
|
|
sub balloon_motion { |
|
3366
|
|
|
|
|
|
|
my ($txt, $x, $y) = @_ ; |
|
3367
|
|
|
|
|
|
|
my ($offset_x, $offset_y) = ($x + 4, $y + 4) ; |
|
3368
|
|
|
|
|
|
|
my $self = $DB::window ; |
|
3369
|
|
|
|
|
|
|
my $txt2 = $self->{'text'} ; |
|
3370
|
|
|
|
|
|
|
my $data ; |
|
3371
|
|
|
|
|
|
|
|
|
3372
|
|
|
|
|
|
|
$self->{'balloon_coord'} = "$offset_x,$offset_y" ; |
|
3373
|
|
|
|
|
|
|
|
|
3374
|
|
|
|
|
|
|
$x -= $txt->rootx ; |
|
3375
|
|
|
|
|
|
|
$y -= $txt->rooty ; |
|
3376
|
|
|
|
|
|
|
# |
|
3377
|
|
|
|
|
|
|
# Post an event that will cause us to put up a popup |
|
3378
|
|
|
|
|
|
|
# |
|
3379
|
|
|
|
|
|
|
|
|
3380
|
|
|
|
|
|
|
if( $txt2->tagRanges('sel') ) { # check to see if 'sel' tag exists (return undef value) |
|
3381
|
|
|
|
|
|
|
$data = $txt2->get("sel.first", "sel.last") ; # get the text between the 'first' and 'last' point of the sel (selection) tag |
|
3382
|
|
|
|
|
|
|
} |
|
3383
|
|
|
|
|
|
|
else { |
|
3384
|
|
|
|
|
|
|
$data = $DB::window->retrieve_text_expr($x, $y) ; |
|
3385
|
|
|
|
|
|
|
} |
|
3386
|
|
|
|
|
|
|
|
|
3387
|
|
|
|
|
|
|
if( !$data ) { |
|
3388
|
|
|
|
|
|
|
$self->{'balloon_expr'} = "" ; |
|
3389
|
|
|
|
|
|
|
return 0 ; |
|
3390
|
|
|
|
|
|
|
} |
|
3391
|
|
|
|
|
|
|
|
|
3392
|
|
|
|
|
|
|
return 0 if ($data eq $self->{'balloon_expr'}) ; # nevermind if it's the same expression |
|
3393
|
|
|
|
|
|
|
|
|
3394
|
|
|
|
|
|
|
$self->{'event'} = 'balloon_eval' ; |
|
3395
|
|
|
|
|
|
|
$self->{'balloon_expr'} = $data ; |
|
3396
|
|
|
|
|
|
|
|
|
3397
|
|
|
|
|
|
|
return 1 ; # ballon will be canceled and a new one put up(maybe) |
|
3398
|
|
|
|
|
|
|
} # end of balloon_motion |
|
3399
|
|
|
|
|
|
|
|
|
3400
|
|
|
|
|
|
|
sub retrieve_text_expr { |
|
3401
|
|
|
|
|
|
|
my($self, $x, $y) = @_ ; |
|
3402
|
|
|
|
|
|
|
my $txt = $self->{'text'} ; |
|
3403
|
|
|
|
|
|
|
|
|
3404
|
|
|
|
|
|
|
my $coord = "\@$x,$y" ; |
|
3405
|
|
|
|
|
|
|
|
|
3406
|
|
|
|
|
|
|
my($idx, $col, $data, $offset) ; |
|
3407
|
|
|
|
|
|
|
|
|
3408
|
|
|
|
|
|
|
($col, $idx) = line_number_from_coord($txt, $coord) ; |
|
3409
|
|
|
|
|
|
|
|
|
3410
|
|
|
|
|
|
|
$offset = $Devel::ptkdb::linenumber_length + 1 ; # line number text + 1 space |
|
3411
|
|
|
|
|
|
|
|
|
3412
|
|
|
|
|
|
|
return undef if $col < $offset ; # no posting |
|
3413
|
|
|
|
|
|
|
|
|
3414
|
|
|
|
|
|
|
$col -= $offset ; |
|
3415
|
|
|
|
|
|
|
|
|
3416
|
|
|
|
|
|
|
local(*dbline) = $main::{'_<' . $self->{current_file}} ; |
|
3417
|
|
|
|
|
|
|
|
|
3418
|
|
|
|
|
|
|
return undef if( !defined $dbline[$idx] || $dbline[$idx] == 0 ) ; # no executable text, no real variable(?) |
|
3419
|
|
|
|
|
|
|
|
|
3420
|
|
|
|
|
|
|
$data = $dbline[$idx] ; |
|
3421
|
|
|
|
|
|
|
|
|
3422
|
|
|
|
|
|
|
# if we're sitting over white space, leave |
|
3423
|
|
|
|
|
|
|
my $len = length $data ; |
|
3424
|
|
|
|
|
|
|
return unless $data && $col && $len > 0 ; |
|
3425
|
|
|
|
|
|
|
|
|
3426
|
|
|
|
|
|
|
return if substr($data, $col, 1) =~ /\s/ ; |
|
3427
|
|
|
|
|
|
|
|
|
3428
|
|
|
|
|
|
|
# walk backwards till we find some whitespace |
|
3429
|
|
|
|
|
|
|
|
|
3430
|
|
|
|
|
|
|
$col = $len if $len < $col ; |
|
3431
|
|
|
|
|
|
|
while( --$col >= 0 ) { |
|
3432
|
|
|
|
|
|
|
last if substr($data, $col, 1) =~ /[\s\$\@\%]/ ; |
|
3433
|
|
|
|
|
|
|
} |
|
3434
|
|
|
|
|
|
|
|
|
3435
|
|
|
|
|
|
|
substr($data, $col) =~ /^([\$\@\%][a-zA-Z0-9_]+)/ ; |
|
3436
|
|
|
|
|
|
|
|
|
3437
|
|
|
|
|
|
|
return $1 ; |
|
3438
|
|
|
|
|
|
|
} |
|
3439
|
|
|
|
|
|
|
|
|
3440
|
|
|
|
|
|
|
# |
|
3441
|
|
|
|
|
|
|
# after DB::eval get's us a result |
|
3442
|
|
|
|
|
|
|
# |
|
3443
|
|
|
|
|
|
|
sub code_motion_eval { |
|
3444
|
|
|
|
|
|
|
my ($self, @result) = @_ ; |
|
3445
|
|
|
|
|
|
|
my $str ; |
|
3446
|
|
|
|
|
|
|
|
|
3447
|
|
|
|
|
|
|
if( exists $self->{'balloon_dumper'} ) { |
|
3448
|
|
|
|
|
|
|
|
|
3449
|
|
|
|
|
|
|
my $d = $self->{'balloon_dumper'} ; |
|
3450
|
|
|
|
|
|
|
|
|
3451
|
|
|
|
|
|
|
$d->Reset() ; |
|
3452
|
|
|
|
|
|
|
$d->Values( [ $#result == 0 ? @result : \@result ] ) ; |
|
3453
|
|
|
|
|
|
|
|
|
3454
|
|
|
|
|
|
|
if( $d->can('Dumpxs') ) { |
|
3455
|
|
|
|
|
|
|
$str = $d->Dumpxs() ; |
|
3456
|
|
|
|
|
|
|
} |
|
3457
|
|
|
|
|
|
|
else { |
|
3458
|
|
|
|
|
|
|
$str = $d->Dump() ; |
|
3459
|
|
|
|
|
|
|
} |
|
3460
|
|
|
|
|
|
|
|
|
3461
|
|
|
|
|
|
|
chomp($str) ; |
|
3462
|
|
|
|
|
|
|
} |
|
3463
|
|
|
|
|
|
|
else { |
|
3464
|
|
|
|
|
|
|
$str = "@result" ; |
|
3465
|
|
|
|
|
|
|
} |
|
3466
|
|
|
|
|
|
|
|
|
3467
|
|
|
|
|
|
|
# |
|
3468
|
|
|
|
|
|
|
# Cut the string down to 1024 characters to keep from |
|
3469
|
|
|
|
|
|
|
# overloading the balloon window |
|
3470
|
|
|
|
|
|
|
# |
|
3471
|
|
|
|
|
|
|
|
|
3472
|
|
|
|
|
|
|
$self->{'expr_ballon_msg'} = "$self->{'balloon_expr'} = " . substr $str, 0, 1024 ; |
|
3473
|
|
|
|
|
|
|
} # end of code motion eval |
|
3474
|
|
|
|
|
|
|
|
|
3475
|
|
|
|
|
|
|
# |
|
3476
|
|
|
|
|
|
|
# Subroutine called when we enter DB::DB() |
|
3477
|
|
|
|
|
|
|
# In other words when the target script 'stops' |
|
3478
|
|
|
|
|
|
|
# in the Debugger |
|
3479
|
|
|
|
|
|
|
# |
|
3480
|
|
|
|
|
|
|
sub EnterActions { |
|
3481
|
|
|
|
|
|
|
my($self) = @_ ; |
|
3482
|
|
|
|
|
|
|
|
|
3483
|
|
|
|
|
|
|
# $self->{'main_window'}->Unbusy() ; |
|
3484
|
|
|
|
|
|
|
|
|
3485
|
|
|
|
|
|
|
} # end of EnterActions |
|
3486
|
|
|
|
|
|
|
|
|
3487
|
|
|
|
|
|
|
# |
|
3488
|
|
|
|
|
|
|
# Subroutine called when we return from DB::DB() |
|
3489
|
|
|
|
|
|
|
# When the target script resumes. |
|
3490
|
|
|
|
|
|
|
# |
|
3491
|
|
|
|
|
|
|
sub LeaveActions { |
|
3492
|
|
|
|
|
|
|
my($self) = @_ ; |
|
3493
|
|
|
|
|
|
|
|
|
3494
|
|
|
|
|
|
|
# $self->{'main_window'}->Busy() ; |
|
3495
|
|
|
|
|
|
|
} # end of LeaveActions |
|
3496
|
|
|
|
|
|
|
|
|
3497
|
|
|
|
|
|
|
|
|
3498
|
|
|
|
|
|
|
sub BEGIN { |
|
3499
|
|
|
|
|
|
|
$Devel::ptkdb::scriptName = $0 ; |
|
3500
|
|
|
|
|
|
|
@Devel::ptkdb::script_args = @ARGV ; # copy args |
|
3501
|
|
|
|
|
|
|
|
|
3502
|
|
|
|
|
|
|
} |
|
3503
|
|
|
|
|
|
|
|
|
3504
|
|
|
|
|
|
|
## |
|
3505
|
|
|
|
|
|
|
## Save the ptkdb state file and restart the debugger |
|
3506
|
|
|
|
|
|
|
## |
|
3507
|
|
|
|
|
|
|
sub DoRestart { |
|
3508
|
|
|
|
|
|
|
my($fname) ; |
|
3509
|
|
|
|
|
|
|
|
|
3510
|
|
|
|
|
|
|
$fname = $ENV{'TMP'} || $ENV{'TMPDIR'} || $ENV{'TMP_DIR'} || $ENV{'TEMP'} || $ENV{'HOME'} ; |
|
3511
|
|
|
|
|
|
|
$fname .= '/' if $fname ; |
|
3512
|
|
|
|
|
|
|
$fname = "" unless $fname ; |
|
3513
|
|
|
|
|
|
|
|
|
3514
|
|
|
|
|
|
|
$fname .= "ptkdb_restart_state$$" ; |
|
3515
|
|
|
|
|
|
|
|
|
3516
|
|
|
|
|
|
|
# print "saving temp state file $fname\n" ; |
|
3517
|
|
|
|
|
|
|
|
|
3518
|
|
|
|
|
|
|
&DB::save_state_file($fname) ; |
|
3519
|
|
|
|
|
|
|
|
|
3520
|
|
|
|
|
|
|
$ENV{'PTKDB_RESTART_STATE_FILE'} = $fname ; |
|
3521
|
|
|
|
|
|
|
|
|
3522
|
|
|
|
|
|
|
## |
|
3523
|
|
|
|
|
|
|
## build up the command to do the restart |
|
3524
|
|
|
|
|
|
|
## |
|
3525
|
|
|
|
|
|
|
|
|
3526
|
|
|
|
|
|
|
$fname = "perl -w -d:ptkdb $Devel::ptkdb::scriptName @Devel::ptkdb::script_args" ; |
|
3527
|
|
|
|
|
|
|
|
|
3528
|
|
|
|
|
|
|
# print "$$ doing a restart with $fname\n" ; |
|
3529
|
|
|
|
|
|
|
|
|
3530
|
|
|
|
|
|
|
exec $fname ; |
|
3531
|
|
|
|
|
|
|
|
|
3532
|
|
|
|
|
|
|
} # end of DoRestart |
|
3533
|
|
|
|
|
|
|
|
|
3534
|
|
|
|
|
|
|
## |
|
3535
|
|
|
|
|
|
|
## Enables/Disables the feature where we stop |
|
3536
|
|
|
|
|
|
|
## if we've encountered a perl warning such as: |
|
3537
|
|
|
|
|
|
|
## "Use of uninitialized value at undef_warn.pl line N" |
|
3538
|
|
|
|
|
|
|
## |
|
3539
|
|
|
|
|
|
|
|
|
3540
|
|
|
|
|
|
|
sub stop_on_warning_cb { |
|
3541
|
|
|
|
|
|
|
&$DB::ptkdb::warn_sig_save() if $DB::ptkdb::warn_sig_save ; # call any previously registered warning |
|
3542
|
|
|
|
|
|
|
$DB::window->DoAlert(@_) ; |
|
3543
|
|
|
|
|
|
|
$DB::single = 1 ; # forces debugger to stop next time |
|
3544
|
|
|
|
|
|
|
} |
|
3545
|
|
|
|
|
|
|
|
|
3546
|
|
|
|
|
|
|
sub set_stop_on_warning { |
|
3547
|
|
|
|
|
|
|
|
|
3548
|
|
|
|
|
|
|
if( $DB::ptkdb::stop_on_warning ) { |
|
3549
|
|
|
|
|
|
|
|
|
3550
|
|
|
|
|
|
|
return if $DB::ptkdb::warn_sig_save == \&stop_on_warning_cb ; # prevents recursion |
|
3551
|
|
|
|
|
|
|
|
|
3552
|
|
|
|
|
|
|
$DB::ptkdb::warn_sig_save = $SIG{'__WARN__'} if $SIG{'__WARN__'} ; |
|
3553
|
|
|
|
|
|
|
$SIG{'__WARN__'} = \&stop_on_warning_cb ; |
|
3554
|
|
|
|
|
|
|
} |
|
3555
|
|
|
|
|
|
|
else { |
|
3556
|
|
|
|
|
|
|
## |
|
3557
|
|
|
|
|
|
|
## Restore any previous warning signal |
|
3558
|
|
|
|
|
|
|
## |
|
3559
|
|
|
|
|
|
|
local($^W) = 0 ; |
|
3560
|
|
|
|
|
|
|
$SIG{'__WARN__'} = $DB::ptkdb::warn_sig_save ; |
|
3561
|
|
|
|
|
|
|
} |
|
3562
|
|
|
|
|
|
|
} # end of set_stop_on_warning |
|
3563
|
|
|
|
|
|
|
|
|
3564
|
|
|
|
|
|
|
1 ; # end of Devel::ptkdb |
|
3565
|
|
|
|
|
|
|
|
|
3566
|
|
|
|
|
|
|
package DB ; |
|
3567
|
|
|
|
|
|
|
|
|
3568
|
|
|
|
|
|
|
use vars '$VERSION', '$header' ; |
|
3569
|
|
|
|
|
|
|
|
|
3570
|
|
|
|
|
|
|
$VERSION = '1.1091' ; |
|
3571
|
|
|
|
|
|
|
$header = "ptkdb.pm version $DB::VERSION"; |
|
3572
|
|
|
|
|
|
|
$DB::window->{current_file} = "" ; |
|
3573
|
|
|
|
|
|
|
|
|
3574
|
|
|
|
|
|
|
# |
|
3575
|
|
|
|
|
|
|
# Here's the clue... |
|
3576
|
|
|
|
|
|
|
# eval only seems to eval the context of |
|
3577
|
|
|
|
|
|
|
# the executing script while in the DB |
|
3578
|
|
|
|
|
|
|
# package. When we had updateExprs in the Devel::ptkdb |
|
3579
|
|
|
|
|
|
|
# package eval would turn up an undef result. |
|
3580
|
|
|
|
|
|
|
# |
|
3581
|
|
|
|
|
|
|
|
|
3582
|
|
|
|
|
|
|
sub updateExprs { |
|
3583
|
|
|
|
|
|
|
my ($package) = @_ ; |
|
3584
|
|
|
|
|
|
|
# |
|
3585
|
|
|
|
|
|
|
# Update expressions |
|
3586
|
|
|
|
|
|
|
# |
|
3587
|
|
|
|
|
|
|
$DB::window->deleteAllExprs() ; |
|
3588
|
|
|
|
|
|
|
my ($expr, @result); |
|
3589
|
|
|
|
|
|
|
|
|
3590
|
|
|
|
|
|
|
foreach $expr ( @{$DB::window->{'expr_list'}} ) { |
|
3591
|
|
|
|
|
|
|
next if length $expr == 0 ; |
|
3592
|
|
|
|
|
|
|
|
|
3593
|
|
|
|
|
|
|
@result = &DB::dbeval($package, $expr->{'expr'}) ; |
|
3594
|
|
|
|
|
|
|
|
|
3595
|
|
|
|
|
|
|
if( @result == 1 ) { |
|
3596
|
|
|
|
|
|
|
$DB::window->insertExpr([ $result[0] ], $DB::window->{'data_list'}, $result[0], $expr->{'expr'}, $expr->{'depth'}) ; |
|
3597
|
|
|
|
|
|
|
} |
|
3598
|
|
|
|
|
|
|
else { |
|
3599
|
|
|
|
|
|
|
$DB::window->insertExpr([ \@result ], $DB::window->{'data_list'}, \@result, $expr->{'expr'}, $expr->{'depth'}) ; |
|
3600
|
|
|
|
|
|
|
} |
|
3601
|
|
|
|
|
|
|
} |
|
3602
|
|
|
|
|
|
|
|
|
3603
|
|
|
|
|
|
|
} # end of updateExprs |
|
3604
|
|
|
|
|
|
|
|
|
3605
|
|
|
|
|
|
|
no strict ; # turning strict off (shame shame) because we keep getting errrs for the local(*dbline) |
|
3606
|
|
|
|
|
|
|
|
|
3607
|
|
|
|
|
|
|
# |
|
3608
|
|
|
|
|
|
|
# returns true if line is breakable |
|
3609
|
|
|
|
|
|
|
# |
|
3610
|
|
|
|
|
|
|
use Carp ; |
|
3611
|
|
|
|
|
|
|
sub checkdbline($$) { |
|
3612
|
|
|
|
|
|
|
my ($fname, $lineno) = @_ ; |
|
3613
|
|
|
|
|
|
|
|
|
3614
|
|
|
|
|
|
|
return 0 unless $fname; # we're getting an undef here on 'Restart...' |
|
3615
|
|
|
|
|
|
|
|
|
3616
|
|
|
|
|
|
|
local($^W) = 0 ; # spares us warnings under -w |
|
3617
|
|
|
|
|
|
|
local(*dbline) = $main::{'_<' . $fname} ; |
|
3618
|
|
|
|
|
|
|
|
|
3619
|
|
|
|
|
|
|
my $flag = $dbline[$lineno] != 0 ; |
|
3620
|
|
|
|
|
|
|
|
|
3621
|
|
|
|
|
|
|
return $flag; |
|
3622
|
|
|
|
|
|
|
|
|
3623
|
|
|
|
|
|
|
} # end of checkdbline |
|
3624
|
|
|
|
|
|
|
|
|
3625
|
|
|
|
|
|
|
# |
|
3626
|
|
|
|
|
|
|
# sets a breakpoint 'through' a magic |
|
3627
|
|
|
|
|
|
|
# variable that perl is able to interpert |
|
3628
|
|
|
|
|
|
|
# |
|
3629
|
|
|
|
|
|
|
sub setdbline($$$) { |
|
3630
|
|
|
|
|
|
|
my ($fname, $lineno, $value) = @_ ; |
|
3631
|
|
|
|
|
|
|
local(*dbline) = $main::{'_<' . $fname}; |
|
3632
|
|
|
|
|
|
|
|
|
3633
|
|
|
|
|
|
|
$dbline{$lineno} = $value ; |
|
3634
|
|
|
|
|
|
|
} # end of setdbline |
|
3635
|
|
|
|
|
|
|
|
|
3636
|
|
|
|
|
|
|
sub getdbline($$) { |
|
3637
|
|
|
|
|
|
|
my ($fname, $lineno) = @_ ; |
|
3638
|
|
|
|
|
|
|
local(*dbline) = $main::{'_<' . $fname}; |
|
3639
|
|
|
|
|
|
|
return $dbline{$lineno} ; |
|
3640
|
|
|
|
|
|
|
} # end of getdbline |
|
3641
|
|
|
|
|
|
|
|
|
3642
|
|
|
|
|
|
|
sub getdbtextline { |
|
3643
|
|
|
|
|
|
|
my ($fname, $lineno) = @_ ; |
|
3644
|
|
|
|
|
|
|
local(*dbline) = $main::{'_<' . $fname}; |
|
3645
|
|
|
|
|
|
|
return $dbline[$lineno] ; |
|
3646
|
|
|
|
|
|
|
} # end of getdbline |
|
3647
|
|
|
|
|
|
|
|
|
3648
|
|
|
|
|
|
|
|
|
3649
|
|
|
|
|
|
|
sub cleardbline($$;&) { |
|
3650
|
|
|
|
|
|
|
my ($fname, $lineno, $clearsub) = @_ ; |
|
3651
|
|
|
|
|
|
|
local(*dbline) = $main::{'_<' . $fname}; |
|
3652
|
|
|
|
|
|
|
my $value ; # just in case we want it for something |
|
3653
|
|
|
|
|
|
|
|
|
3654
|
|
|
|
|
|
|
$value = $dbline{$lineno} ; |
|
3655
|
|
|
|
|
|
|
delete $dbline{$lineno} ; |
|
3656
|
|
|
|
|
|
|
&$clearsub($value) if $value && $clearsub ; |
|
3657
|
|
|
|
|
|
|
|
|
3658
|
|
|
|
|
|
|
return $value ; |
|
3659
|
|
|
|
|
|
|
} # end of cleardbline |
|
3660
|
|
|
|
|
|
|
|
|
3661
|
|
|
|
|
|
|
sub clearalldblines(;&) { |
|
3662
|
|
|
|
|
|
|
my ($clearsub) = @_ ; |
|
3663
|
|
|
|
|
|
|
my ($key, $value, $brkPt, $dbkey) ; |
|
3664
|
|
|
|
|
|
|
local(*dbline) ; |
|
3665
|
|
|
|
|
|
|
|
|
3666
|
|
|
|
|
|
|
while ( ($key, $value) = each %main:: ) { # key loop |
|
3667
|
|
|
|
|
|
|
next unless $key =~ /^_ ; |
|
3668
|
|
|
|
|
|
|
*dbline = $value ; |
|
3669
|
|
|
|
|
|
|
|
|
3670
|
|
|
|
|
|
|
foreach $dbkey (keys %dbline) { |
|
3671
|
|
|
|
|
|
|
$brkPt = $dbline{$dbkey} ; |
|
3672
|
|
|
|
|
|
|
delete $dbline{$dbkey} ; |
|
3673
|
|
|
|
|
|
|
next unless $brkPt && $clearSub ; |
|
3674
|
|
|
|
|
|
|
&$clearsub($brkPt) ; # if specificed, call the sub routine to clear the breakpoint |
|
3675
|
|
|
|
|
|
|
} |
|
3676
|
|
|
|
|
|
|
|
|
3677
|
|
|
|
|
|
|
} # end of key loop |
|
3678
|
|
|
|
|
|
|
|
|
3679
|
|
|
|
|
|
|
} # end of clearalldblines |
|
3680
|
|
|
|
|
|
|
|
|
3681
|
|
|
|
|
|
|
sub getdblineindexes { |
|
3682
|
|
|
|
|
|
|
my ($fname) = @_ ; |
|
3683
|
|
|
|
|
|
|
local(*dbline) = $main::{'_<' . $fname} ; |
|
3684
|
|
|
|
|
|
|
return keys %dbline ; |
|
3685
|
|
|
|
|
|
|
} # end of getdblineindexes |
|
3686
|
|
|
|
|
|
|
|
|
3687
|
|
|
|
|
|
|
sub getbreakpoints { |
|
3688
|
|
|
|
|
|
|
my (@fnames) = @_ ; |
|
3689
|
|
|
|
|
|
|
my ($fname, @retList) ; |
|
3690
|
|
|
|
|
|
|
|
|
3691
|
|
|
|
|
|
|
foreach $fname (@fnames) { |
|
3692
|
|
|
|
|
|
|
next unless $main::{'_<' . $fname} ; |
|
3693
|
|
|
|
|
|
|
local(*dbline) = $main::{'_<' . $fname} ; |
|
3694
|
|
|
|
|
|
|
push @retList, values %dbline ; |
|
3695
|
|
|
|
|
|
|
} |
|
3696
|
|
|
|
|
|
|
return @retList ; |
|
3697
|
|
|
|
|
|
|
} # end of getbreakpoints |
|
3698
|
|
|
|
|
|
|
|
|
3699
|
|
|
|
|
|
|
# |
|
3700
|
|
|
|
|
|
|
# Construct a hash of the files |
|
3701
|
|
|
|
|
|
|
# that have breakpoints to save |
|
3702
|
|
|
|
|
|
|
# |
|
3703
|
|
|
|
|
|
|
sub breakpoints_to_save { |
|
3704
|
|
|
|
|
|
|
my ($file, @breaks, $brkPt, $svBrkPt, $list) ; |
|
3705
|
|
|
|
|
|
|
my ($brkList) ; |
|
3706
|
|
|
|
|
|
|
|
|
3707
|
|
|
|
|
|
|
$brkList = {} ; |
|
3708
|
|
|
|
|
|
|
|
|
3709
|
|
|
|
|
|
|
foreach $file ( keys %main:: ) { # file loop |
|
3710
|
|
|
|
|
|
|
next unless $file =~ /^_ && exists $main::{$file} ; |
|
3711
|
|
|
|
|
|
|
local(*dbline) = $main::{$file} ; |
|
3712
|
|
|
|
|
|
|
|
|
3713
|
|
|
|
|
|
|
next unless @breaks = values %dbline ; |
|
3714
|
|
|
|
|
|
|
$list = [] ; |
|
3715
|
|
|
|
|
|
|
foreach $brkPt ( @breaks ) { |
|
3716
|
|
|
|
|
|
|
|
|
3717
|
|
|
|
|
|
|
$svBrkPt = { %$brkPt } ; # make a copy of it's data |
|
3718
|
|
|
|
|
|
|
|
|
3719
|
|
|
|
|
|
|
push @$list, $svBrkPt ; |
|
3720
|
|
|
|
|
|
|
|
|
3721
|
|
|
|
|
|
|
} # end of breakpoint loop |
|
3722
|
|
|
|
|
|
|
|
|
3723
|
|
|
|
|
|
|
$brkList->{$file} = $list ; |
|
3724
|
|
|
|
|
|
|
|
|
3725
|
|
|
|
|
|
|
} # end of file loop |
|
3726
|
|
|
|
|
|
|
|
|
3727
|
|
|
|
|
|
|
return $brkList ; |
|
3728
|
|
|
|
|
|
|
|
|
3729
|
|
|
|
|
|
|
} # end of breakpoints_to_save |
|
3730
|
|
|
|
|
|
|
|
|
3731
|
|
|
|
|
|
|
# |
|
3732
|
|
|
|
|
|
|
# When we restore breakpoints from a state file |
|
3733
|
|
|
|
|
|
|
# they've often 'moved' because the file |
|
3734
|
|
|
|
|
|
|
# has been editted. |
|
3735
|
|
|
|
|
|
|
# |
|
3736
|
|
|
|
|
|
|
# We search for the line starting with the original line number, |
|
3737
|
|
|
|
|
|
|
# then we walk it back 20 lines, then with line right after the |
|
3738
|
|
|
|
|
|
|
# orginal line number and walk forward 20 lines. |
|
3739
|
|
|
|
|
|
|
# |
|
3740
|
|
|
|
|
|
|
# NOTE: dbline is expected to be 'local' |
|
3741
|
|
|
|
|
|
|
# when called |
|
3742
|
|
|
|
|
|
|
# |
|
3743
|
|
|
|
|
|
|
sub fix_breakpoints { |
|
3744
|
|
|
|
|
|
|
my(@brkPts) = @_ ; |
|
3745
|
|
|
|
|
|
|
my($startLine, $endLine, $nLines, $brkPt) ; |
|
3746
|
|
|
|
|
|
|
my (@retList) ; |
|
3747
|
|
|
|
|
|
|
local($^W) = 0 ; |
|
3748
|
|
|
|
|
|
|
|
|
3749
|
|
|
|
|
|
|
$nLines = scalar @dbline ; |
|
3750
|
|
|
|
|
|
|
|
|
3751
|
|
|
|
|
|
|
foreach $brkPt (@brkPts) { |
|
3752
|
|
|
|
|
|
|
|
|
3753
|
|
|
|
|
|
|
$startLine = $brkPt->{'line'} > 20 ? $brkPt->{'line'} - 20 : 0 ; |
|
3754
|
|
|
|
|
|
|
$endLine = $brkPt->{'line'} < $nLines - 20 ? $brkPt->{'line'} + 20 : $nLines ; |
|
3755
|
|
|
|
|
|
|
|
|
3756
|
|
|
|
|
|
|
for( (reverse $startLine..$brkPt->{'line'}), $brkPt->{'line'} + 1 .. $endLine ) { |
|
3757
|
|
|
|
|
|
|
next unless $brkPt->{'text'} eq $dbline[$_] ; |
|
3758
|
|
|
|
|
|
|
$brkPt->{'line'} = $_ ; |
|
3759
|
|
|
|
|
|
|
push @retList, $brkPt ; |
|
3760
|
|
|
|
|
|
|
last ; |
|
3761
|
|
|
|
|
|
|
} |
|
3762
|
|
|
|
|
|
|
} # end of breakpoint list |
|
3763
|
|
|
|
|
|
|
|
|
3764
|
|
|
|
|
|
|
return @retList ; |
|
3765
|
|
|
|
|
|
|
|
|
3766
|
|
|
|
|
|
|
} # end of fix_breakpoints |
|
3767
|
|
|
|
|
|
|
|
|
3768
|
|
|
|
|
|
|
# |
|
3769
|
|
|
|
|
|
|
# Restore breakpoints saved above |
|
3770
|
|
|
|
|
|
|
# |
|
3771
|
|
|
|
|
|
|
sub restore_breakpoints_from_save { |
|
3772
|
|
|
|
|
|
|
my ($brkList) = @_ ; |
|
3773
|
|
|
|
|
|
|
my ($offset, $key, $list, $brkPt, @newList) ; |
|
3774
|
|
|
|
|
|
|
|
|
3775
|
|
|
|
|
|
|
while ( ($key, $list) = each %$brkList ) { # reinsert loop |
|
3776
|
|
|
|
|
|
|
next unless exists $main::{$key} ; |
|
3777
|
|
|
|
|
|
|
local(*dbline) = $main::{$key} ; |
|
3778
|
|
|
|
|
|
|
|
|
3779
|
|
|
|
|
|
|
$offset = 0 ; |
|
3780
|
|
|
|
|
|
|
$offset = 1 if $dbline[1] =~ /use\s+.*Devel::_?ptkdb/ ; |
|
3781
|
|
|
|
|
|
|
|
|
3782
|
|
|
|
|
|
|
@newList = fix_breakpoints(@$list) ; |
|
3783
|
|
|
|
|
|
|
|
|
3784
|
|
|
|
|
|
|
foreach $brkPt ( @newList ) { |
|
3785
|
|
|
|
|
|
|
if( !&DB::checkdbline($key, $brkPt->{'line'} + $offset) ) { |
|
3786
|
|
|
|
|
|
|
print "Breakpoint $key:$brkPt->{'line'} in config file is not breakable.\n" ; |
|
3787
|
|
|
|
|
|
|
next ; |
|
3788
|
|
|
|
|
|
|
} |
|
3789
|
|
|
|
|
|
|
$dbline{$brkPt->{'line'}} = { %$brkPt } ; # make a fresh copy |
|
3790
|
|
|
|
|
|
|
} |
|
3791
|
|
|
|
|
|
|
} # end of reinsert loop |
|
3792
|
|
|
|
|
|
|
|
|
3793
|
|
|
|
|
|
|
} # end of restore_breakpoints_from_save ; |
|
3794
|
|
|
|
|
|
|
|
|
3795
|
|
|
|
|
|
|
use strict ; |
|
3796
|
|
|
|
|
|
|
|
|
3797
|
|
|
|
|
|
|
sub dbint_handler { |
|
3798
|
|
|
|
|
|
|
my($sigName) = @_ ; |
|
3799
|
|
|
|
|
|
|
$DB::single = 1 ; |
|
3800
|
|
|
|
|
|
|
print "signalled\n" ; |
|
3801
|
|
|
|
|
|
|
} # end of dbint_handler |
|
3802
|
|
|
|
|
|
|
|
|
3803
|
|
|
|
|
|
|
# |
|
3804
|
|
|
|
|
|
|
# Do first time initialization at the startup |
|
3805
|
|
|
|
|
|
|
# of DB::DB |
|
3806
|
|
|
|
|
|
|
# |
|
3807
|
|
|
|
|
|
|
sub Initialize { |
|
3808
|
|
|
|
|
|
|
my ($fName) = @_ ; |
|
3809
|
|
|
|
|
|
|
return if $DB::ptkdb::isInitialized ; |
|
3810
|
|
|
|
|
|
|
$DB::ptkdb::isInitialized = 1 ; |
|
3811
|
|
|
|
|
|
|
|
|
3812
|
|
|
|
|
|
|
$DB::window = new Devel::ptkdb ; |
|
3813
|
|
|
|
|
|
|
|
|
3814
|
|
|
|
|
|
|
$DB::window->do_user_init_files() ; |
|
3815
|
|
|
|
|
|
|
|
|
3816
|
|
|
|
|
|
|
|
|
3817
|
|
|
|
|
|
|
$DB::dbint_handler_save = $SIG{'INT'} unless $DB::sigint_disable ; # saves the old handler |
|
3818
|
|
|
|
|
|
|
$SIG{'INT'} = "DB::dbint_handler" unless $DB::sigint_disable ; |
|
3819
|
|
|
|
|
|
|
|
|
3820
|
|
|
|
|
|
|
# Save the file name we started up with |
|
3821
|
|
|
|
|
|
|
$DB::startupFname = $fName ; |
|
3822
|
|
|
|
|
|
|
|
|
3823
|
|
|
|
|
|
|
# Check for a 'restart' file |
|
3824
|
|
|
|
|
|
|
|
|
3825
|
|
|
|
|
|
|
if( $ENV{'PTKDB_RESTART_STATE_FILE'} && $Devel::ptkdb::DataDumperAvailable && -e $ENV{'PTKDB_RESTART_STATE_FILE'} ) { |
|
3826
|
|
|
|
|
|
|
## |
|
3827
|
|
|
|
|
|
|
## Restore expressions and breakpoints in state file |
|
3828
|
|
|
|
|
|
|
## |
|
3829
|
|
|
|
|
|
|
$DB::window->restoreStateFile($ENV{'PTKDB_RESTART_STATE_FILE'}) ; |
|
3830
|
|
|
|
|
|
|
unlink $ENV{'PTKDB_RESTART_STATE_FILE'} ; # delete state file |
|
3831
|
|
|
|
|
|
|
|
|
3832
|
|
|
|
|
|
|
# print "restoring state from $ENV{'PTKDB_RESTART_STATE_FILE'}\n" ; |
|
3833
|
|
|
|
|
|
|
|
|
3834
|
|
|
|
|
|
|
$ENV{'PTKDB_RESTART_STATE_FILE'} = "" ; # clear entry |
|
3835
|
|
|
|
|
|
|
} |
|
3836
|
|
|
|
|
|
|
else { |
|
3837
|
|
|
|
|
|
|
&DB::restoreState($fName) if $Devel::ptkdb::DataDumperAvailable ; |
|
3838
|
|
|
|
|
|
|
} |
|
3839
|
|
|
|
|
|
|
|
|
3840
|
|
|
|
|
|
|
} # end of Initialize |
|
3841
|
|
|
|
|
|
|
|
|
3842
|
|
|
|
|
|
|
sub restoreState { |
|
3843
|
|
|
|
|
|
|
my($fName) = @_ ; |
|
3844
|
|
|
|
|
|
|
my ($stateFile, $files, $expr_list, $eval_saved_text, $main_win_geometry, $restoreName) ; |
|
3845
|
|
|
|
|
|
|
|
|
3846
|
|
|
|
|
|
|
$stateFile = makeFileSaveName($fName) ; |
|
3847
|
|
|
|
|
|
|
|
|
3848
|
|
|
|
|
|
|
if( -e $stateFile && -r $stateFile ) { |
|
3849
|
|
|
|
|
|
|
($files, $expr_list, $eval_saved_text, $main_win_geometry) = $DB::window->get_state($stateFile) ; |
|
3850
|
|
|
|
|
|
|
&DB::restore_breakpoints_from_save($files) ; |
|
3851
|
|
|
|
|
|
|
$DB::window->{'expr_list'} = $expr_list if defined $expr_list ; |
|
3852
|
|
|
|
|
|
|
$DB::window->{eval_saved_text} = $eval_saved_text ; |
|
3853
|
|
|
|
|
|
|
|
|
3854
|
|
|
|
|
|
|
if ( $main_win_geometry ) { |
|
3855
|
|
|
|
|
|
|
# restore the height and width of the window |
|
3856
|
|
|
|
|
|
|
$DB::window->{main_window}->geometry($main_win_geometry) ; |
|
3857
|
|
|
|
|
|
|
} |
|
3858
|
|
|
|
|
|
|
} |
|
3859
|
|
|
|
|
|
|
|
|
3860
|
|
|
|
|
|
|
} # end of Restore State |
|
3861
|
|
|
|
|
|
|
|
|
3862
|
|
|
|
|
|
|
sub makeFileSaveName { |
|
3863
|
|
|
|
|
|
|
my ($fName) = @_ ; |
|
3864
|
|
|
|
|
|
|
my $saveName = $fName ; |
|
3865
|
|
|
|
|
|
|
|
|
3866
|
|
|
|
|
|
|
if( $saveName =~ /.p[lm]$/ ) { |
|
3867
|
|
|
|
|
|
|
$saveName =~ s/.pl$/.ptkdb/ ; |
|
3868
|
|
|
|
|
|
|
} |
|
3869
|
|
|
|
|
|
|
else { |
|
3870
|
|
|
|
|
|
|
$saveName .= ".ptkdb" ; |
|
3871
|
|
|
|
|
|
|
} |
|
3872
|
|
|
|
|
|
|
|
|
3873
|
|
|
|
|
|
|
return $saveName ; |
|
3874
|
|
|
|
|
|
|
} # end of makeFileSaveName |
|
3875
|
|
|
|
|
|
|
|
|
3876
|
|
|
|
|
|
|
sub save_state_file { |
|
3877
|
|
|
|
|
|
|
my($fname) = @_ ; |
|
3878
|
|
|
|
|
|
|
my($files, $d, $saveStr) ; |
|
3879
|
|
|
|
|
|
|
|
|
3880
|
|
|
|
|
|
|
$files = &DB::breakpoints_to_save() ; |
|
3881
|
|
|
|
|
|
|
|
|
3882
|
|
|
|
|
|
|
$d = Data::Dumper->new( [ $files, $DB::window->{'expr_list'}, "" ], |
|
3883
|
|
|
|
|
|
|
[ "files", "expr_list", "eval_saved_text" ] ) ; |
|
3884
|
|
|
|
|
|
|
|
|
3885
|
|
|
|
|
|
|
$d->Purity(1) ; |
|
3886
|
|
|
|
|
|
|
if( Data::Dumper->can('Dumpxs') ) { |
|
3887
|
|
|
|
|
|
|
$saveStr = $d->Dumpxs() ; |
|
3888
|
|
|
|
|
|
|
} else { |
|
3889
|
|
|
|
|
|
|
$saveStr = $d->Dump() ; |
|
3890
|
|
|
|
|
|
|
} |
|
3891
|
|
|
|
|
|
|
|
|
3892
|
|
|
|
|
|
|
local(*F) ; |
|
3893
|
|
|
|
|
|
|
open F, ">$fname" || die "Couldn't open file $fname" ; |
|
3894
|
|
|
|
|
|
|
|
|
3895
|
|
|
|
|
|
|
print F $saveStr || die "Couldn't write file" ; |
|
3896
|
|
|
|
|
|
|
|
|
3897
|
|
|
|
|
|
|
close F ; |
|
3898
|
|
|
|
|
|
|
} # end of save_state_file |
|
3899
|
|
|
|
|
|
|
|
|
3900
|
|
|
|
|
|
|
sub SaveState { |
|
3901
|
|
|
|
|
|
|
my($name_in) = @_ ; |
|
3902
|
|
|
|
|
|
|
my ($top, $entry, $okayBtn, $win) ; |
|
3903
|
|
|
|
|
|
|
my ($fname, $saveSub, $cancelSub, $saveName, $eval_saved_text, $d) ; |
|
3904
|
|
|
|
|
|
|
my ($files, $main_win_geometry); |
|
3905
|
|
|
|
|
|
|
# |
|
3906
|
|
|
|
|
|
|
# Create our default name |
|
3907
|
|
|
|
|
|
|
# |
|
3908
|
|
|
|
|
|
|
$win = $DB::window ; |
|
3909
|
|
|
|
|
|
|
|
|
3910
|
|
|
|
|
|
|
# |
|
3911
|
|
|
|
|
|
|
# Extract the height and width of our window |
|
3912
|
|
|
|
|
|
|
# |
|
3913
|
|
|
|
|
|
|
$main_win_geometry = $win->{main_window}->geometry ; |
|
3914
|
|
|
|
|
|
|
|
|
3915
|
|
|
|
|
|
|
if ( defined $win->{save_box} ) { |
|
3916
|
|
|
|
|
|
|
$win->{save_box}->raise ; |
|
3917
|
|
|
|
|
|
|
$win->{save_box}->focus ; |
|
3918
|
|
|
|
|
|
|
return ; |
|
3919
|
|
|
|
|
|
|
} |
|
3920
|
|
|
|
|
|
|
|
|
3921
|
|
|
|
|
|
|
$saveName = $name_in || makeFileSaveName($DB::startupFname) ; |
|
3922
|
|
|
|
|
|
|
|
|
3923
|
|
|
|
|
|
|
|
|
3924
|
|
|
|
|
|
|
|
|
3925
|
|
|
|
|
|
|
$saveSub = sub { |
|
3926
|
|
|
|
|
|
|
$win->{'event'} = 'null' ; |
|
3927
|
|
|
|
|
|
|
|
|
3928
|
|
|
|
|
|
|
my $saveStr ; |
|
3929
|
|
|
|
|
|
|
|
|
3930
|
|
|
|
|
|
|
delete $win->{save_box} ; |
|
3931
|
|
|
|
|
|
|
|
|
3932
|
|
|
|
|
|
|
if( exists $win->{eval_window} ) { |
|
3933
|
|
|
|
|
|
|
$eval_saved_text = $win->{eval_text}->get('0.0', 'end') ; |
|
3934
|
|
|
|
|
|
|
} |
|
3935
|
|
|
|
|
|
|
else { |
|
3936
|
|
|
|
|
|
|
$eval_saved_text = $win->{eval_saved_text} ; |
|
3937
|
|
|
|
|
|
|
} |
|
3938
|
|
|
|
|
|
|
|
|
3939
|
|
|
|
|
|
|
$files = &DB::breakpoints_to_save() ; |
|
3940
|
|
|
|
|
|
|
|
|
3941
|
|
|
|
|
|
|
$d = Data::Dumper->new( [ $files, $win->{'expr_list'}, $eval_saved_text, $main_win_geometry ], |
|
3942
|
|
|
|
|
|
|
[ "files", "expr_list", "eval_saved_text", "main_win_geometry"] ) ; |
|
3943
|
|
|
|
|
|
|
|
|
3944
|
|
|
|
|
|
|
$d->Purity(1) ; |
|
3945
|
|
|
|
|
|
|
if( Data::Dumper->can('Dumpxs') ) { |
|
3946
|
|
|
|
|
|
|
$saveStr = $d->Dumpxs() ; |
|
3947
|
|
|
|
|
|
|
} else { |
|
3948
|
|
|
|
|
|
|
$saveStr = $d->Dump() ; |
|
3949
|
|
|
|
|
|
|
} |
|
3950
|
|
|
|
|
|
|
|
|
3951
|
|
|
|
|
|
|
local(*F) ; |
|
3952
|
|
|
|
|
|
|
eval { |
|
3953
|
|
|
|
|
|
|
open F, ">$saveName" || die "Couldn't open file $saveName" ; |
|
3954
|
|
|
|
|
|
|
|
|
3955
|
|
|
|
|
|
|
print F $saveStr || die "Couldn't write file" ; |
|
3956
|
|
|
|
|
|
|
|
|
3957
|
|
|
|
|
|
|
close F ; |
|
3958
|
|
|
|
|
|
|
} ; |
|
3959
|
|
|
|
|
|
|
$win->DoAlert($@) if $@ ; |
|
3960
|
|
|
|
|
|
|
} ; # end of save sub |
|
3961
|
|
|
|
|
|
|
|
|
3962
|
|
|
|
|
|
|
$cancelSub = sub { |
|
3963
|
|
|
|
|
|
|
delete $win->{'save_box'} |
|
3964
|
|
|
|
|
|
|
} ; # end of cancel sub |
|
3965
|
|
|
|
|
|
|
|
|
3966
|
|
|
|
|
|
|
# |
|
3967
|
|
|
|
|
|
|
# Create a dialog |
|
3968
|
|
|
|
|
|
|
# |
|
3969
|
|
|
|
|
|
|
|
|
3970
|
|
|
|
|
|
|
$win->{'save_box'} = $win->simplePromptBox("Save Config?", $saveName, $saveSub, $cancelSub) ; |
|
3971
|
|
|
|
|
|
|
|
|
3972
|
|
|
|
|
|
|
} # end of SaveState |
|
3973
|
|
|
|
|
|
|
|
|
3974
|
|
|
|
|
|
|
sub RestoreState { |
|
3975
|
|
|
|
|
|
|
my ($top, $restoreSub) ; |
|
3976
|
|
|
|
|
|
|
|
|
3977
|
|
|
|
|
|
|
$restoreSub = sub { |
|
3978
|
|
|
|
|
|
|
$DB::window->restoreStateFile($Devel::ptkdb::promptString) ; |
|
3979
|
|
|
|
|
|
|
} ; |
|
3980
|
|
|
|
|
|
|
|
|
3981
|
|
|
|
|
|
|
$top = $DB::window->simplePromptBox("Restore Config?", makeFileSaveName($DB::startupFname), $restoreSub) ; |
|
3982
|
|
|
|
|
|
|
|
|
3983
|
|
|
|
|
|
|
} # end of RestoreState |
|
3984
|
|
|
|
|
|
|
|
|
3985
|
|
|
|
|
|
|
sub SetStepOverBreakPoint { |
|
3986
|
|
|
|
|
|
|
my ($offset) = @_ ; |
|
3987
|
|
|
|
|
|
|
$DB::step_over_depth = $DB::subroutine_depth + ($offset ? $offset : 0) ; |
|
3988
|
|
|
|
|
|
|
} # end of SetStepOverBreakPoint |
|
3989
|
|
|
|
|
|
|
|
|
3990
|
|
|
|
|
|
|
# |
|
3991
|
|
|
|
|
|
|
# NOTE: It may be logical and somewhat more economical |
|
3992
|
|
|
|
|
|
|
# lines of codewise to set $DB::step_over_depth_saved |
|
3993
|
|
|
|
|
|
|
# when we enter the subroutine, but this gets called |
|
3994
|
|
|
|
|
|
|
# for EVERY callable line of code in a program that |
|
3995
|
|
|
|
|
|
|
# is being debugged, so we try to save every line of |
|
3996
|
|
|
|
|
|
|
# execution that we can. |
|
3997
|
|
|
|
|
|
|
# |
|
3998
|
|
|
|
|
|
|
sub isBreakPoint { |
|
3999
|
|
|
|
|
|
|
my ($fname, $line, $package) = @_ ; |
|
4000
|
|
|
|
|
|
|
my ($brkPt) ; |
|
4001
|
|
|
|
|
|
|
|
|
4002
|
|
|
|
|
|
|
if ( $DB::single && ($DB::step_over_depth < $DB::subroutine_depth) && ($DB::step_over_depth > 0) && !$DB::on) { |
|
4003
|
|
|
|
|
|
|
$DB::single = 0 ; |
|
4004
|
|
|
|
|
|
|
return 0 ; |
|
4005
|
|
|
|
|
|
|
} |
|
4006
|
|
|
|
|
|
|
# |
|
4007
|
|
|
|
|
|
|
# doing a step over/in |
|
4008
|
|
|
|
|
|
|
# |
|
4009
|
|
|
|
|
|
|
|
|
4010
|
|
|
|
|
|
|
if( $DB::single || $DB::signal ) { |
|
4011
|
|
|
|
|
|
|
$DB::single = 0 ; |
|
4012
|
|
|
|
|
|
|
$DB::signal = 0 ; |
|
4013
|
|
|
|
|
|
|
$DB::subroutine_depth = $DB::subroutine_depth ; |
|
4014
|
|
|
|
|
|
|
return 1 ; |
|
4015
|
|
|
|
|
|
|
} |
|
4016
|
|
|
|
|
|
|
# |
|
4017
|
|
|
|
|
|
|
# 1st Check to see if there is even a breakpoint there. |
|
4018
|
|
|
|
|
|
|
# 2nd If there is a breakpoint check to see if it's check box control is 'on' |
|
4019
|
|
|
|
|
|
|
# 3rd If there is any kind of expression, evaluate it and see if it's true. |
|
4020
|
|
|
|
|
|
|
# |
|
4021
|
|
|
|
|
|
|
$brkPt = &DB::getdbline($fname, $line) ; |
|
4022
|
|
|
|
|
|
|
|
|
4023
|
|
|
|
|
|
|
return 0 if( !$brkPt || !$brkPt->{'value'} || !breakPointEvalExpr($brkPt, $package) ) ; |
|
4024
|
|
|
|
|
|
|
|
|
4025
|
|
|
|
|
|
|
&DB::cleardbline($fname, $line) if( $brkPt->{'type'} eq 'temp' ) ; |
|
4026
|
|
|
|
|
|
|
|
|
4027
|
|
|
|
|
|
|
$DB::subroutine_depth = $DB::subroutine_depth ; |
|
4028
|
|
|
|
|
|
|
|
|
4029
|
|
|
|
|
|
|
return 1 ; |
|
4030
|
|
|
|
|
|
|
} # end of isBreakPoint |
|
4031
|
|
|
|
|
|
|
|
|
4032
|
|
|
|
|
|
|
# |
|
4033
|
|
|
|
|
|
|
# Check the breakpoint expression to see if it |
|
4034
|
|
|
|
|
|
|
# is true. |
|
4035
|
|
|
|
|
|
|
# |
|
4036
|
|
|
|
|
|
|
sub breakPointEvalExpr { |
|
4037
|
|
|
|
|
|
|
my ($brkPt, $package) = @_ ; |
|
4038
|
|
|
|
|
|
|
my (@result) ; |
|
4039
|
|
|
|
|
|
|
|
|
4040
|
|
|
|
|
|
|
return 1 unless $brkPt->{expr} ; # return if there is no expression |
|
4041
|
|
|
|
|
|
|
|
|
4042
|
|
|
|
|
|
|
no strict ; |
|
4043
|
|
|
|
|
|
|
|
|
4044
|
|
|
|
|
|
|
@result = &DB::dbeval($package, $brkPt->{'expr'}) ; |
|
4045
|
|
|
|
|
|
|
|
|
4046
|
|
|
|
|
|
|
use strict ; |
|
4047
|
|
|
|
|
|
|
|
|
4048
|
|
|
|
|
|
|
$DB::window->DoAlert($@) if $@ ; |
|
4049
|
|
|
|
|
|
|
|
|
4050
|
|
|
|
|
|
|
return $result[0] or @result ; # we could have a case where the 1st element is undefined |
|
4051
|
|
|
|
|
|
|
# but subsequent elements are defined |
|
4052
|
|
|
|
|
|
|
|
|
4053
|
|
|
|
|
|
|
} # end of breakPointEvalExpr |
|
4054
|
|
|
|
|
|
|
|
|
4055
|
|
|
|
|
|
|
# |
|
4056
|
|
|
|
|
|
|
# Evaluate the given expression, return the result. |
|
4057
|
|
|
|
|
|
|
# MUST BE CALLED from within DB::DB in order for it |
|
4058
|
|
|
|
|
|
|
# to properly interpret the vars |
|
4059
|
|
|
|
|
|
|
# |
|
4060
|
|
|
|
|
|
|
sub dbeval { |
|
4061
|
|
|
|
|
|
|
my($ptkdb__package, $ptkdb__expr) = @_ ; |
|
4062
|
|
|
|
|
|
|
my(@ptkdb__result, $ptkdb__str) ; |
|
4063
|
|
|
|
|
|
|
my(@ptkdb_args) ; |
|
4064
|
|
|
|
|
|
|
local($^W) = 0 ; # temporarily turn off warnings |
|
4065
|
|
|
|
|
|
|
|
|
4066
|
|
|
|
|
|
|
no strict ; |
|
4067
|
|
|
|
|
|
|
# |
|
4068
|
|
|
|
|
|
|
# This substitution is done so that |
|
4069
|
|
|
|
|
|
|
# we return HASH, as opposed to an ARRAY. |
|
4070
|
|
|
|
|
|
|
# An expression of %hash results in a |
|
4071
|
|
|
|
|
|
|
# list of key/value pairs. |
|
4072
|
|
|
|
|
|
|
# |
|
4073
|
|
|
|
|
|
|
|
|
4074
|
|
|
|
|
|
|
$ptkdb__expr =~ s/^\s*%/\\%/o ; |
|
4075
|
|
|
|
|
|
|
|
|
4076
|
|
|
|
|
|
|
@_ = @DB::saved_args ; # replace @_ arg array with what we came in with |
|
4077
|
|
|
|
|
|
|
|
|
4078
|
|
|
|
|
|
|
@ptkdb__result = eval <<__EVAL__ ; |
|
4079
|
|
|
|
|
|
|
|
|
4080
|
|
|
|
|
|
|
|
|
4081
|
|
|
|
|
|
|
\$\@ = \$DB::save_err ; |
|
4082
|
|
|
|
|
|
|
|
|
4083
|
|
|
|
|
|
|
package $ptkdb__package ; |
|
4084
|
|
|
|
|
|
|
|
|
4085
|
|
|
|
|
|
|
$ptkdb__expr ; |
|
4086
|
|
|
|
|
|
|
|
|
4087
|
|
|
|
|
|
|
__EVAL__ |
|
4088
|
|
|
|
|
|
|
|
|
4089
|
|
|
|
|
|
|
@ptkdb__result = ("ERROR ($@)") if $@ ; |
|
4090
|
|
|
|
|
|
|
|
|
4091
|
|
|
|
|
|
|
use strict ; |
|
4092
|
|
|
|
|
|
|
|
|
4093
|
|
|
|
|
|
|
return @ptkdb__result ; |
|
4094
|
|
|
|
|
|
|
} # end of dbeval |
|
4095
|
|
|
|
|
|
|
|
|
4096
|
|
|
|
|
|
|
# |
|
4097
|
|
|
|
|
|
|
# Call back we give to our 'quit' button |
|
4098
|
|
|
|
|
|
|
# and binding to the WM_DELETE_WINDOW protocol |
|
4099
|
|
|
|
|
|
|
# to quit the debugger. |
|
4100
|
|
|
|
|
|
|
# |
|
4101
|
|
|
|
|
|
|
sub dbexit { |
|
4102
|
|
|
|
|
|
|
exit ; |
|
4103
|
|
|
|
|
|
|
} # end of dbexit |
|
4104
|
|
|
|
|
|
|
|
|
4105
|
|
|
|
|
|
|
# |
|
4106
|
|
|
|
|
|
|
# This is the primary entry point for the debugger. When a perl program |
|
4107
|
|
|
|
|
|
|
# is parsed with the -d(in our case -d:ptkdb) option set the parser will |
|
4108
|
|
|
|
|
|
|
# insert a call to DB::DB in front of every excecutable statement. |
|
4109
|
|
|
|
|
|
|
# |
|
4110
|
|
|
|
|
|
|
# Refs: Progamming Perl 2nd Edition, Larry Wall, O'Reilly & Associates, Chapter 8 |
|
4111
|
|
|
|
|
|
|
# |
|
4112
|
|
|
|
|
|
|
|
|
4113
|
|
|
|
|
|
|
|
|
4114
|
|
|
|
|
|
|
## |
|
4115
|
|
|
|
|
|
|
## Since perl 5.8.0 we need to predeclare the sub DB{} at the start of the |
|
4116
|
|
|
|
|
|
|
## package or else the compilation fails. We need to disable warnings though |
|
4117
|
|
|
|
|
|
|
## since in 5.6.x we get warnings on the sub DB begin redeclared. Using |
|
4118
|
|
|
|
|
|
|
## local($^W) = 0 will leave warnings disabled for the rest of the compile |
|
4119
|
|
|
|
|
|
|
## and we don't want that. |
|
4120
|
|
|
|
|
|
|
## |
|
4121
|
|
|
|
|
|
|
my($saveW) ; |
|
4122
|
|
|
|
|
|
|
sub BEGIN { |
|
4123
|
|
|
|
|
|
|
$saveW = $^W ; |
|
4124
|
|
|
|
|
|
|
$^W = 0 ; |
|
4125
|
|
|
|
|
|
|
} |
|
4126
|
|
|
|
|
|
|
|
|
4127
|
|
|
|
|
|
|
no strict ; |
|
4128
|
|
|
|
|
|
|
sub DB { |
|
4129
|
|
|
|
|
|
|
@DB::saved_args = @_ ; # save arg context |
|
4130
|
|
|
|
|
|
|
$DB::save_err = $@ ; # save value of $@ |
|
4131
|
|
|
|
|
|
|
my ($package, $filename, $line) = caller ; |
|
4132
|
|
|
|
|
|
|
my ($stop, $cnt) ; |
|
4133
|
|
|
|
|
|
|
|
|
4134
|
|
|
|
|
|
|
$^W = $saveW ; |
|
4135
|
|
|
|
|
|
|
unless( $DB::ptkdb::isInitialized ) { |
|
4136
|
|
|
|
|
|
|
return if( $filename ne $0 ) ; # not in our target file |
|
4137
|
|
|
|
|
|
|
&DB::Initialize($filename) ; |
|
4138
|
|
|
|
|
|
|
} |
|
4139
|
|
|
|
|
|
|
|
|
4140
|
|
|
|
|
|
|
if (!isBreakPoint($filename, $line, $package) ) { |
|
4141
|
|
|
|
|
|
|
$DB::single = 0 ; |
|
4142
|
|
|
|
|
|
|
$@ = $DB::save_err ; |
|
4143
|
|
|
|
|
|
|
return ; |
|
4144
|
|
|
|
|
|
|
} |
|
4145
|
|
|
|
|
|
|
|
|
4146
|
|
|
|
|
|
|
if ( !$DB::window ) { # not setup yet |
|
4147
|
|
|
|
|
|
|
$@ = $DB::save_err ; |
|
4148
|
|
|
|
|
|
|
return ; |
|
4149
|
|
|
|
|
|
|
} |
|
4150
|
|
|
|
|
|
|
|
|
4151
|
|
|
|
|
|
|
$DB::window->setup_main_window() unless $DB::window->{'main_window'} ; |
|
4152
|
|
|
|
|
|
|
|
|
4153
|
|
|
|
|
|
|
$DB::window->EnterActions() ; |
|
4154
|
|
|
|
|
|
|
|
|
4155
|
|
|
|
|
|
|
my ($saveP) ; |
|
4156
|
|
|
|
|
|
|
$saveP = $^P ; |
|
4157
|
|
|
|
|
|
|
$^P = 0 ; |
|
4158
|
|
|
|
|
|
|
|
|
4159
|
|
|
|
|
|
|
$DB::on = 1 ; |
|
4160
|
|
|
|
|
|
|
|
|
4161
|
|
|
|
|
|
|
# |
|
4162
|
|
|
|
|
|
|
# The user can specify this variable in one of the startup files, |
|
4163
|
|
|
|
|
|
|
# this will make the debugger run right after startup without |
|
4164
|
|
|
|
|
|
|
# the user having to press the 'run' button. |
|
4165
|
|
|
|
|
|
|
# |
|
4166
|
|
|
|
|
|
|
if( $DB::no_stop_at_start ) { |
|
4167
|
|
|
|
|
|
|
$DB::no_stop_at_start = 0 ; |
|
4168
|
|
|
|
|
|
|
$DB::on = 0 ; |
|
4169
|
|
|
|
|
|
|
$@ = $DB::save_err ; |
|
4170
|
|
|
|
|
|
|
return ; |
|
4171
|
|
|
|
|
|
|
} |
|
4172
|
|
|
|
|
|
|
|
|
4173
|
|
|
|
|
|
|
if( !$DB::sigint_disable ) { |
|
4174
|
|
|
|
|
|
|
$SIG{'INT'} = $DB::dbint_handler_save if $DB::dbint_handler_save ; # restore original signal handler |
|
4175
|
|
|
|
|
|
|
$SIG{'INT'} = "DB::dbexit" unless $DB::dbint_handler_save ; |
|
4176
|
|
|
|
|
|
|
} |
|
4177
|
|
|
|
|
|
|
|
|
4178
|
|
|
|
|
|
|
#$DB::window->{main_window}->raise() ; # bring us to the top make sure OUR event loop runs |
|
4179
|
|
|
|
|
|
|
$DB::window->{main_window}->focus() ; |
|
4180
|
|
|
|
|
|
|
|
|
4181
|
|
|
|
|
|
|
$DB::window->set_file($filename, $line) ; |
|
4182
|
|
|
|
|
|
|
# |
|
4183
|
|
|
|
|
|
|
# Refresh the exprs to see if anything has changed |
|
4184
|
|
|
|
|
|
|
# |
|
4185
|
|
|
|
|
|
|
updateExprs($package) ; |
|
4186
|
|
|
|
|
|
|
|
|
4187
|
|
|
|
|
|
|
# |
|
4188
|
|
|
|
|
|
|
# Update subs Page if necessary |
|
4189
|
|
|
|
|
|
|
# |
|
4190
|
|
|
|
|
|
|
$cnt = scalar keys %DB::sub ; |
|
4191
|
|
|
|
|
|
|
if ( $cnt != $DB::window->{'subs_list_cnt'} && $DB::window->{'subs_page_activated'} ) { |
|
4192
|
|
|
|
|
|
|
$DB::window->fill_subs_page() ; |
|
4193
|
|
|
|
|
|
|
$DB::window->{'subs_list_cnt'} = $cnt ; |
|
4194
|
|
|
|
|
|
|
} |
|
4195
|
|
|
|
|
|
|
# |
|
4196
|
|
|
|
|
|
|
# Update the subroutine stack menu |
|
4197
|
|
|
|
|
|
|
# |
|
4198
|
|
|
|
|
|
|
$DB::window->refresh_stack_menu() ; |
|
4199
|
|
|
|
|
|
|
|
|
4200
|
|
|
|
|
|
|
$DB::window->{run_flag} = 1 ; |
|
4201
|
|
|
|
|
|
|
|
|
4202
|
|
|
|
|
|
|
my ($evt, @result, $r) ; |
|
4203
|
|
|
|
|
|
|
|
|
4204
|
|
|
|
|
|
|
for( ; ; ) { |
|
4205
|
|
|
|
|
|
|
# |
|
4206
|
|
|
|
|
|
|
# we wait here for something to do |
|
4207
|
|
|
|
|
|
|
# |
|
4208
|
|
|
|
|
|
|
$evt = $DB::window->main_loop() ; |
|
4209
|
|
|
|
|
|
|
|
|
4210
|
|
|
|
|
|
|
last if( $evt eq 'step' ) ; |
|
4211
|
|
|
|
|
|
|
|
|
4212
|
|
|
|
|
|
|
$DB::single = 0 if ($evt eq 'run' ) ; |
|
4213
|
|
|
|
|
|
|
|
|
4214
|
|
|
|
|
|
|
if ($evt eq 'balloon_eval' ) { |
|
4215
|
|
|
|
|
|
|
$DB::window->code_motion_eval(&DB::dbeval($package, $DB::window->{'balloon_expr'})) ; |
|
4216
|
|
|
|
|
|
|
next ; |
|
4217
|
|
|
|
|
|
|
} |
|
4218
|
|
|
|
|
|
|
|
|
4219
|
|
|
|
|
|
|
if ( $evt eq 'qexpr' ) { |
|
4220
|
|
|
|
|
|
|
my $str ; |
|
4221
|
|
|
|
|
|
|
@result = &DB::dbeval($package, $DB::window->{'qexpr'}) ; |
|
4222
|
|
|
|
|
|
|
$DB::window->{'quick_entry'}->delete(0, 'end') ; # clear old text |
|
4223
|
|
|
|
|
|
|
if (exists $DB::window->{'quick_dumper'}) { |
|
4224
|
|
|
|
|
|
|
$DB::window->{'quick_dumper'}->Reset() ; |
|
4225
|
|
|
|
|
|
|
$DB::window->{'quick_dumper'}->Values( [ $#result == 0 ? @result : \@result ] ) ; |
|
4226
|
|
|
|
|
|
|
if( $DB::window->{'quick_dumper'}->can('Dumpxs') ) { |
|
4227
|
|
|
|
|
|
|
$str = $DB::window->{'quick_dumper'}->Dumpxs() ; |
|
4228
|
|
|
|
|
|
|
} |
|
4229
|
|
|
|
|
|
|
else { |
|
4230
|
|
|
|
|
|
|
$str = $DB::window->{'quick_dumper'}->Dump() ; |
|
4231
|
|
|
|
|
|
|
} |
|
4232
|
|
|
|
|
|
|
} |
|
4233
|
|
|
|
|
|
|
else { |
|
4234
|
|
|
|
|
|
|
$str = "@result" ; |
|
4235
|
|
|
|
|
|
|
} |
|
4236
|
|
|
|
|
|
|
$DB::window->{'quick_entry'}->insert(0, $str) ; #enter the text |
|
4237
|
|
|
|
|
|
|
$DB::window->{'quick_entry'}->selectionRange(0, 'end') ; # select it |
|
4238
|
|
|
|
|
|
|
$evt = 'update' ; # force an update on the expressions |
|
4239
|
|
|
|
|
|
|
} |
|
4240
|
|
|
|
|
|
|
|
|
4241
|
|
|
|
|
|
|
if( $evt eq 'expr' ) { |
|
4242
|
|
|
|
|
|
|
# |
|
4243
|
|
|
|
|
|
|
# Append the new expression to the list |
|
4244
|
|
|
|
|
|
|
# but first check to make sure that we don't |
|
4245
|
|
|
|
|
|
|
# already have it. |
|
4246
|
|
|
|
|
|
|
# |
|
4247
|
|
|
|
|
|
|
|
|
4248
|
|
|
|
|
|
|
if ( grep $_->{'expr'} eq $DB::window->{'expr'}, @{$DB::window->{'expr_list'}} ) { |
|
4249
|
|
|
|
|
|
|
$DB::window->DoAlert("$DB::window->{'expr'} is already listed") ; |
|
4250
|
|
|
|
|
|
|
next ; |
|
4251
|
|
|
|
|
|
|
} |
|
4252
|
|
|
|
|
|
|
|
|
4253
|
|
|
|
|
|
|
@result = &DB::dbeval($package, $DB::window->{expr}) ; |
|
4254
|
|
|
|
|
|
|
|
|
4255
|
|
|
|
|
|
|
if( @result == 1 ) { |
|
4256
|
|
|
|
|
|
|
$r = $DB::window->insertExpr([ $result[0] ], $DB::window->{'data_list'}, $result[0], $DB::window->{'expr'}, $Devel::ptkdb::expr_depth) ; |
|
4257
|
|
|
|
|
|
|
} |
|
4258
|
|
|
|
|
|
|
else { |
|
4259
|
|
|
|
|
|
|
$r = $DB::window->insertExpr([ \@result ], $DB::window->{'data_list'}, \@result, $DB::window->{'expr'}, $Devel::ptkdb::expr_depth) ; |
|
4260
|
|
|
|
|
|
|
} |
|
4261
|
|
|
|
|
|
|
|
|
4262
|
|
|
|
|
|
|
# |
|
4263
|
|
|
|
|
|
|
# $r will be 1 if the expression was added succesfully, 0 if not, |
|
4264
|
|
|
|
|
|
|
# and it if wasn't added sucessfully it won't be reevalled the |
|
4265
|
|
|
|
|
|
|
# next time through. |
|
4266
|
|
|
|
|
|
|
# |
|
4267
|
|
|
|
|
|
|
push @{$DB::window->{'expr_list'}}, { 'expr' => $DB::window->{'expr'}, 'depth' => $Devel::ptkdb::expr_depth } if $r ; |
|
4268
|
|
|
|
|
|
|
|
|
4269
|
|
|
|
|
|
|
next ; |
|
4270
|
|
|
|
|
|
|
} |
|
4271
|
|
|
|
|
|
|
if( $evt eq 'update' ) { |
|
4272
|
|
|
|
|
|
|
updateExprs($package) ; |
|
4273
|
|
|
|
|
|
|
next ; |
|
4274
|
|
|
|
|
|
|
} |
|
4275
|
|
|
|
|
|
|
if( $evt eq 'reeval' ) { |
|
4276
|
|
|
|
|
|
|
# |
|
4277
|
|
|
|
|
|
|
# Reevaluate the contents of the expression eval window |
|
4278
|
|
|
|
|
|
|
# |
|
4279
|
|
|
|
|
|
|
my $txt = $DB::window->{'eval_text'}->get('0.0', 'end') ; |
|
4280
|
|
|
|
|
|
|
my @result = &DB::dbeval($package, $txt) ; |
|
4281
|
|
|
|
|
|
|
|
|
4282
|
|
|
|
|
|
|
$DB::window->updateEvalWindow(@result) ; |
|
4283
|
|
|
|
|
|
|
|
|
4284
|
|
|
|
|
|
|
next ; |
|
4285
|
|
|
|
|
|
|
} |
|
4286
|
|
|
|
|
|
|
last ; |
|
4287
|
|
|
|
|
|
|
} |
|
4288
|
|
|
|
|
|
|
$^P = $saveP ; |
|
4289
|
|
|
|
|
|
|
$SIG{'INT'} = "DB::dbint_handler" unless $DB::sigint_disable ; # set our signal handler |
|
4290
|
|
|
|
|
|
|
|
|
4291
|
|
|
|
|
|
|
$DB::window->LeaveActions() ; |
|
4292
|
|
|
|
|
|
|
|
|
4293
|
|
|
|
|
|
|
$@ = $DB::save_err ; |
|
4294
|
|
|
|
|
|
|
$DB::on = 0 ; |
|
4295
|
|
|
|
|
|
|
} # end of DB |
|
4296
|
|
|
|
|
|
|
|
|
4297
|
|
|
|
|
|
|
## |
|
4298
|
|
|
|
|
|
|
## in this case we do not use local($^W) since we would like warnings |
|
4299
|
|
|
|
|
|
|
## to be issued past this point, and the localized copy of $^W will not |
|
4300
|
|
|
|
|
|
|
## go out of scope until the end of compilation |
|
4301
|
|
|
|
|
|
|
## |
|
4302
|
|
|
|
|
|
|
## |
|
4303
|
|
|
|
|
|
|
|
|
4304
|
|
|
|
|
|
|
# |
|
4305
|
|
|
|
|
|
|
# This is another place where we'll try and keep the |
|
4306
|
|
|
|
|
|
|
# code as 'lite' as possible to prevent the debugger |
|
4307
|
|
|
|
|
|
|
# from slowing down the user's application |
|
4308
|
|
|
|
|
|
|
# |
|
4309
|
|
|
|
|
|
|
# When a perl program is parsed with the -d(in our case a -d:ptkdb) option |
|
4310
|
|
|
|
|
|
|
# the parser will route all subroutine calls through here, setting $DB::sub |
|
4311
|
|
|
|
|
|
|
# to the name of the subroutine to be called, leaving it to the debugger to |
|
4312
|
|
|
|
|
|
|
# make the actual subroutine call and do any pre or post processing it may |
|
4313
|
|
|
|
|
|
|
# need to do. In our case we take the opportunity to track the depth of the call |
|
4314
|
|
|
|
|
|
|
# stack so that we can update our 'Stack' menu when we stop. |
|
4315
|
|
|
|
|
|
|
# |
|
4316
|
|
|
|
|
|
|
# Refs: Progamming Perl 2nd Edition, Larry Wall, O'Reilly & Associates, Chapter 8 |
|
4317
|
|
|
|
|
|
|
# |
|
4318
|
|
|
|
|
|
|
# |
|
4319
|
|
|
|
|
|
|
sub sub { |
|
4320
|
|
|
|
|
|
|
my ($result, @result) ; |
|
4321
|
|
|
|
|
|
|
# |
|
4322
|
|
|
|
|
|
|
# See NOTES(1) |
|
4323
|
|
|
|
|
|
|
# |
|
4324
|
|
|
|
|
|
|
$DB::subroutine_depth += 1 unless $DB::on ; |
|
4325
|
|
|
|
|
|
|
$DB::single = 0 if ( ($DB::step_over_depth < $DB::subroutine_depth) && ($DB::step_over_depth >= 0) && !$DB::on) ; |
|
4326
|
|
|
|
|
|
|
|
|
4327
|
|
|
|
|
|
|
if( wantarray ) { |
|
4328
|
|
|
|
|
|
|
# |
|
4329
|
|
|
|
|
|
|
# array context |
|
4330
|
|
|
|
|
|
|
# |
|
4331
|
|
|
|
|
|
|
no strict ; # otherwise perl gripes about calling the sub by the reference |
|
4332
|
|
|
|
|
|
|
@result = &$DB::sub ; # call the subroutine by name |
|
4333
|
|
|
|
|
|
|
use strict ; |
|
4334
|
|
|
|
|
|
|
|
|
4335
|
|
|
|
|
|
|
$DB::subroutine_depth -= 1 unless $DB::on ; |
|
4336
|
|
|
|
|
|
|
$DB::single = 1 if ($DB::step_over_depth >= $DB::subroutine_depth && !$DB::on) ; |
|
4337
|
|
|
|
|
|
|
return @result ; |
|
4338
|
|
|
|
|
|
|
} |
|
4339
|
|
|
|
|
|
|
elsif(defined wantarray) { |
|
4340
|
|
|
|
|
|
|
|
|
4341
|
|
|
|
|
|
|
# |
|
4342
|
|
|
|
|
|
|
# scalar context |
|
4343
|
|
|
|
|
|
|
# |
|
4344
|
|
|
|
|
|
|
no strict ; |
|
4345
|
|
|
|
|
|
|
$result = &$DB::sub ; |
|
4346
|
|
|
|
|
|
|
use strict ; |
|
4347
|
|
|
|
|
|
|
|
|
4348
|
|
|
|
|
|
|
$DB::subroutine_depth -= 1 unless $DB::on ; |
|
4349
|
|
|
|
|
|
|
$DB::single = 1 if ($DB::step_over_depth >= $DB::subroutine_depth && !$DB::on) ; |
|
4350
|
|
|
|
|
|
|
return $result ; |
|
4351
|
|
|
|
|
|
|
} else { |
|
4352
|
|
|
|
|
|
|
# |
|
4353
|
|
|
|
|
|
|
# void context |
|
4354
|
|
|
|
|
|
|
# |
|
4355
|
|
|
|
|
|
|
|
|
4356
|
|
|
|
|
|
|
no strict ; |
|
4357
|
|
|
|
|
|
|
&$DB::sub ; |
|
4358
|
|
|
|
|
|
|
use strict ; |
|
4359
|
|
|
|
|
|
|
|
|
4360
|
|
|
|
|
|
|
$DB::subroutine_depth -= 1 unless $DB::on ; |
|
4361
|
|
|
|
|
|
|
$DB::single = 1 if ($DB::step_over_depth >= $DB::subroutine_depth && !$DB::on) ; |
|
4362
|
|
|
|
|
|
|
return $result ; |
|
4363
|
|
|
|
|
|
|
|
|
4364
|
|
|
|
|
|
|
return ; |
|
4365
|
|
|
|
|
|
|
} |
|
4366
|
|
|
|
|
|
|
|
|
4367
|
|
|
|
|
|
|
} # end of sub |
|
4368
|
|
|
|
|
|
|
|
|
4369
|
|
|
|
|
|
|
1 ; # return true value |
|
4370
|
|
|
|
|
|
|
|
|
4371
|
|
|
|
|
|
|
# ptkdb.pm,v |
|
4372
|
|
|
|
|
|
|
# Revision 1.15 2004/03/31 02:08:40 aepage |
|
4373
|
|
|
|
|
|
|
# fixes for various lacks of backwards compatiblity in Tk804 |
|
4374
|
|
|
|
|
|
|
# Added a 'bug report' item to the File Menu. |
|
4375
|
|
|
|
|
|
|
# |
|
4376
|
|
|
|
|
|
|
# Revision 1.14 2003/11/20 01:59:40 aepage |
|
4377
|
|
|
|
|
|
|
# version fix |
|
4378
|
|
|
|
|
|
|
# |
|
4379
|
|
|
|
|
|
|
# Revision 1.12 2003/11/20 01:46:45 aepage |
|
4380
|
|
|
|
|
|
|
# Hex Dumper and correction of some parameters for Tk804.025_beta6 |
|
4381
|
|
|
|
|
|
|
# |
|
4382
|
|
|
|
|
|
|
# Revision 1.11 2003/06/26 13:42:49 aepage |
|
4383
|
|
|
|
|
|
|
# fix for chars at the end of win32 platforms. |
|
4384
|
|
|
|
|
|
|
# |
|
4385
|
|
|
|
|
|
|
# Revision 1.10 2003/05/12 14:38:34 aepage |
|
4386
|
|
|
|
|
|
|
# win32 pushback |
|
4387
|
|
|
|
|
|
|
# |
|
4388
|
|
|
|
|
|
|
# Revision 1.9 2003/05/12 13:46:46 aepage |
|
4389
|
|
|
|
|
|
|
# optmization of win32 line fixing |
|
4390
|
|
|
|
|
|
|
# |
|
4391
|
|
|
|
|
|
|
# Revision 1.8 2003/05/11 23:42:20 aepage |
|
4392
|
|
|
|
|
|
|
# fix to remove stray win32 chars |
|
4393
|
|
|
|
|
|
|
# |
|
4394
|
|
|
|
|
|
|
# Revision 1.7 2003/05/11 23:15:26 aepage |
|
4395
|
|
|
|
|
|
|
# email address changes, fixes for perl 5.8.0 |
|
4396
|
|
|
|
|
|
|
# |
|
4397
|
|
|
|
|
|
|
# Revision 1.6 2002/11/28 19:17:43 aepage |
|
4398
|
|
|
|
|
|
|
# Changed many options to widgets and pack from bareword or 'bareword' |
|
4399
|
|
|
|
|
|
|
# to -bareword to support Tk804.024(Devel). |
|
4400
|
|
|
|
|
|
|
# |
|
4401
|
|
|
|
|
|
|
# Revision 1.5 2002/11/25 23:47:03 aepage |
|
4402
|
|
|
|
|
|
|
# A perl debugger package is required to define a subroutine name 'sub'. |
|
4403
|
|
|
|
|
|
|
# This routine is a 'proxy' for handling subroutine calls and allows the |
|
4404
|
|
|
|
|
|
|
# debugger pacakage to track subroutine depth so that it can implement |
|
4405
|
|
|
|
|
|
|
# 'step over', 'step in' and 'return' functionality. It must also |
|
4406
|
|
|
|
|
|
|
# handle the same context as the proxied routine; it must return a |
|
4407
|
|
|
|
|
|
|
# scalar where a scalar was being expected, an array where an array is |
|
4408
|
|
|
|
|
|
|
# being expected and a void where a void was being expected. Ptkdb was |
|
4409
|
|
|
|
|
|
|
# not handling the case for void. 99.9% of the time this will have no |
|
4410
|
|
|
|
|
|
|
# ill effects although it is being handled incorrectly. Ref Programming |
|
4411
|
|
|
|
|
|
|
# Perl 3rd Edition pg 827 |
|
4412
|
|
|
|
|
|
|
# |
|
4413
|
|
|
|
|
|
|
# Revision 1.4 2002/10/24 17:07:10 aepage |
|
4414
|
|
|
|
|
|
|
# fix for warning for undefined value assigend to typeglob during restart |
|
4415
|
|
|
|
|
|
|
# |
|
4416
|
|
|
|
|
|
|
# Revision 1.3 2002/10/20 23:49:51 aepage |
|
4417
|
|
|
|
|
|
|
# |
|
4418
|
|
|
|
|
|
|
# changed email address to aepage@ptkdb.sourceforge.net
|
|
4419
|
|
|
|
|
|
|
#
|
|
4420
|
|
|
|
|
|
|
# localized $^W in dbeval
|
|
4421
|
|
|
|
|
|
|
#
|
|
4422
|
|
|
|
|
|
|
# fix for instances where there is no code in a package.
|
|
4423
|
|
|
|
|
|
|
#
|
|
4424
|
|
|
|
|
|
|
# Initialized $self->{'subs_list_cnt'} in the new constructor to 0 to
|
|
4425
|
|
|
|
|
|
|
# prevent warnings with -w. |
|
4426
|
|
|
|
|
|
|
# |