diff options
| author | Richard M. Stallman | 1998-04-02 05:04:20 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1998-04-02 05:04:20 +0000 |
| commit | c3fd0eea6ccca81df139c141960fca3e14c01a92 (patch) | |
| tree | 4b08f988a4f990765181a06abb9a96bcb5f7cbec | |
| parent | 4a4c24d09e1a8ee6e0f682a56352832a78f57e80 (diff) | |
| download | emacs-c3fd0eea6ccca81df139c141960fca3e14c01a92.tar.gz emacs-c3fd0eea6ccca81df139c141960fca3e14c01a92.zip | |
Add support for jdb (Java debugger).
(jdb): New function.
(gud-jdb-history): New variable.
(gud-jdb-directories): New variable.
(gud-jdb-source-files): New variable.
(gud-jdb-build-source-files-list): New function.
(gud-jdb-package-of-file): New function.
(gud-jdb-class-source-alist): New variable.
(gud-jdb-build-class-source-alist): New function.
(gud-jdb-massage-args): New function.
(gud-jdb-find-source-file): New function.
(gud-jdb-marker-filter): New function.
(gud-jdb-find-file): New function.
(gud-jdb-command-name): New variable.
(gud-perldb-command-name): Variable renamed from perldb-command-name.
| -rw-r--r-- | lisp/gud.el | 295 |
1 files changed, 290 insertions, 5 deletions
diff --git a/lisp/gud.el b/lisp/gud.el index bc42af53da9..47e111bcfe2 100644 --- a/lisp/gud.el +++ b/lisp/gud.el | |||
| @@ -1,10 +1,10 @@ | |||
| 1 | ;;; gud.el --- Grand Unified Debugger mode for gdb, sdb, dbx, xdb or perldb | 1 | ;;; gud.el --- Grand Unified Debugger mode for running GDB and other debuggers |
| 2 | 2 | ||
| 3 | ;; Author: Eric S. Raymond <esr@snark.thyrsus.com> | 3 | ;; Author: Eric S. Raymond <esr@snark.thyrsus.com> |
| 4 | ;; Maintainer: FSF | 4 | ;; Maintainer: FSF |
| 5 | ;; Keywords: unix, tools | 5 | ;; Keywords: unix, tools |
| 6 | 6 | ||
| 7 | ;; Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. | 7 | ;; Copyright (C) 1992, 93, 94, 95, 96, 1998 Free Software Foundation, Inc. |
| 8 | 8 | ||
| 9 | ;; This file is part of GNU Emacs. | 9 | ;; This file is part of GNU Emacs. |
| 10 | 10 | ||
| @@ -34,7 +34,8 @@ | |||
| 34 | ;; wrote the GDB command completion code. Dave Love <d.love@dl.ac.uk> | 34 | ;; wrote the GDB command completion code. Dave Love <d.love@dl.ac.uk> |
| 35 | ;; added the IRIX kluge, re-implemented the Mips-ish variant and added | 35 | ;; added the IRIX kluge, re-implemented the Mips-ish variant and added |
| 36 | ;; a menu. Brian D. Carlstrom <bdc@ai.mit.edu> combined the IRIX kluge with | 36 | ;; a menu. Brian D. Carlstrom <bdc@ai.mit.edu> combined the IRIX kluge with |
| 37 | ;; the gud-xdb-directories hack producing gud-dbx-directories. | 37 | ;; the gud-xdb-directories hack producing gud-dbx-directories. Derek L. Davies |
| 38 | ;; <ddavies@world.std.com> added support for jdb (Java debugger.) | ||
| 38 | 39 | ||
| 39 | ;;; Code: | 40 | ;;; Code: |
| 40 | 41 | ||
| @@ -1228,7 +1229,7 @@ directories if your program contains sources from more than one directory." | |||
| 1228 | (gud-make-debug-menu) | 1229 | (gud-make-debug-menu) |
| 1229 | buf))) | 1230 | buf))) |
| 1230 | 1231 | ||
| 1231 | (defcustom perldb-command-name "perl" | 1232 | (defcustom gud-perldb-command-name "perl" |
| 1232 | "File name for executing Perl." | 1233 | "File name for executing Perl." |
| 1233 | :type 'string | 1234 | :type 'string |
| 1234 | :group 'gud) | 1235 | :group 'gud) |
| @@ -1242,7 +1243,7 @@ and source-file directory for your debugger." | |||
| 1242 | (list (read-from-minibuffer "Run perldb (like this): " | 1243 | (list (read-from-minibuffer "Run perldb (like this): " |
| 1243 | (if (consp gud-perldb-history) | 1244 | (if (consp gud-perldb-history) |
| 1244 | (car gud-perldb-history) | 1245 | (car gud-perldb-history) |
| 1245 | (concat perldb-command-name | 1246 | (concat gud-perldb-command-name |
| 1246 | " " | 1247 | " " |
| 1247 | (or (buffer-file-name) | 1248 | (or (buffer-file-name) |
| 1248 | "-e 0") | 1249 | "-e 0") |
| @@ -1267,6 +1268,290 @@ and source-file directory for your debugger." | |||
| 1267 | (setq paragraph-start comint-prompt-regexp) | 1268 | (setq paragraph-start comint-prompt-regexp) |
| 1268 | (run-hooks 'perldb-mode-hook) | 1269 | (run-hooks 'perldb-mode-hook) |
| 1269 | ) | 1270 | ) |
| 1271 | |||
| 1272 | ;; ====================================================================== | ||
| 1273 | ;; | ||
| 1274 | ;; JDB support. | ||
| 1275 | ;; | ||
| 1276 | ;; AUTHOR: Derek Davies <ddavies@world.std.com> | ||
| 1277 | ;; | ||
| 1278 | ;; CREATED: Sun Feb 22 10:46:38 1998 Derek Davies. | ||
| 1279 | ;; | ||
| 1280 | ;; INVOCATION NOTES: | ||
| 1281 | ;; | ||
| 1282 | ;; You invoke jdb-mode with: | ||
| 1283 | ;; | ||
| 1284 | ;; M-x jdb <enter> | ||
| 1285 | ;; | ||
| 1286 | ;; It responds with: | ||
| 1287 | ;; | ||
| 1288 | ;; Run jdb (like this): jdb | ||
| 1289 | ;; | ||
| 1290 | ;; type any jdb switches followed by the name of the class you'd like to debug. | ||
| 1291 | ;; Supply a fully qualfied classname (these do not have the ".class" extension) | ||
| 1292 | ;; for the name of the class to debug (e.g. "COM.the-kind.ddavies.CoolClass"). | ||
| 1293 | ;; See the known problems section below for restrictions when specifying jdb | ||
| 1294 | ;; command line switches (search forward for '-classpath'). | ||
| 1295 | ;; | ||
| 1296 | ;; You should see something like the following: | ||
| 1297 | ;; | ||
| 1298 | ;; Current directory is ~/src/java/hello/ | ||
| 1299 | ;; Initializing jdb... | ||
| 1300 | ;; 0xed2f6628:class(hello) | ||
| 1301 | ;; > | ||
| 1302 | ;; | ||
| 1303 | ;; To set an initial breakpoint try: | ||
| 1304 | ;; | ||
| 1305 | ;; > stop in hello.main | ||
| 1306 | ;; Breakpoint set in hello.main | ||
| 1307 | ;; > | ||
| 1308 | ;; | ||
| 1309 | ;; To execute the program type: | ||
| 1310 | ;; | ||
| 1311 | ;; > run | ||
| 1312 | ;; run hello | ||
| 1313 | ;; | ||
| 1314 | ;; Breakpoint hit: running ... | ||
| 1315 | ;; hello.main (hello:12) | ||
| 1316 | ;; | ||
| 1317 | ;; Type M-n to step over the current line and M-s to step into it. That, | ||
| 1318 | ;; along with the JDB 'help' command should get you started. The 'quit' | ||
| 1319 | ;; JDB command will get out out of the debugger. | ||
| 1320 | ;; | ||
| 1321 | ;; KNOWN PROBLEMS AND FIXME's: | ||
| 1322 | ;; | ||
| 1323 | ;; Each source file must contain one and only one class or interface | ||
| 1324 | ;; definition. | ||
| 1325 | ;; | ||
| 1326 | ;; Does not grok UNICODE id's. Only ASCII id's are supported. | ||
| 1327 | ;; | ||
| 1328 | ;; Loses when valid package statements are embedded in certain kinds of | ||
| 1329 | ;; comments and/or string literals, but this should be rare. | ||
| 1330 | ;; | ||
| 1331 | ;; You must not put whitespace between "-classpath" and the path to | ||
| 1332 | ;; search for java classes even though it is required when invoking jdb | ||
| 1333 | ;; from the command line. See gud-jdb-massage-args for details. | ||
| 1334 | ;; | ||
| 1335 | ;; ====================================================================== | ||
| 1336 | ;; gud jdb variables and functions | ||
| 1337 | |||
| 1338 | ;; History of argument lists passed to jdb. | ||
| 1339 | (defvar gud-jdb-history nil) | ||
| 1340 | |||
| 1341 | ;; List of Java source file directories. | ||
| 1342 | (defvar gud-jdb-directories (list ".") | ||
| 1343 | "*A list of directories that gud jdb should search for source code. | ||
| 1344 | The file names should be absolute, or relative to the current directory.") | ||
| 1345 | |||
| 1346 | ;; List of the java source files for this debugging session. | ||
| 1347 | (defvar gud-jdb-source-files nil) | ||
| 1348 | |||
| 1349 | ;; Return a list of java source files. PATH gives the directories in | ||
| 1350 | ;; which to search for files with extension EXTN. Normally EXTN is | ||
| 1351 | ;; given as the regular expression "\\.java$" . | ||
| 1352 | (defun gud-jdb-build-source-files-list (path extn) | ||
| 1353 | (apply 'nconc (mapcar (lambda (d) (directory-files d t extn nil)) path))) | ||
| 1354 | |||
| 1355 | ;; Return the package (with trailing period) to which FILE belongs. | ||
| 1356 | ;; Returns "" if FILE is in the default package. BUF is the name of a | ||
| 1357 | ;; buffer into which FILE is read so that it can be searched in order | ||
| 1358 | ;; to determine it's package. As a consequence, the contents of BUF | ||
| 1359 | ;; are erased by this function. | ||
| 1360 | (defun gud-jdb-package-of-file (buf file) | ||
| 1361 | (set-buffer buf) | ||
| 1362 | (insert-file-contents file nil nil nil t) | ||
| 1363 | ;; FIXME: Java IDs are UNICODE strings - this code does not | ||
| 1364 | ;; do the right thing! | ||
| 1365 | ;; FIXME: Does not always ignore contents of comments or string literals. | ||
| 1366 | (if (re-search-forward | ||
| 1367 | "^[ \t]*package[ \t]+\\([a-zA-Z0-9$_\.]+\\)[ \t]*;" nil t) | ||
| 1368 | (concat (match-string 1) ".") | ||
| 1369 | "")) | ||
| 1370 | |||
| 1371 | ;; Association list of fully qualified class names (package + class name) and | ||
| 1372 | ;; their source files. | ||
| 1373 | (defvar gud-jdb-class-source-alist nil) | ||
| 1374 | |||
| 1375 | ;; Return an alist of fully qualified classes and the source files | ||
| 1376 | ;; holding their definitions. SOURCES holds a list of all the source | ||
| 1377 | ;; files to examine. | ||
| 1378 | (defun gud-jdb-build-class-source-alist (sources) | ||
| 1379 | (let ((tmpbuf (get-buffer-create "*gud-jdb-scratch*"))) | ||
| 1380 | (prog1 | ||
| 1381 | (mapcar | ||
| 1382 | (lambda (s) | ||
| 1383 | (cons | ||
| 1384 | (concat | ||
| 1385 | (gud-jdb-package-of-file tmpbuf s) | ||
| 1386 | (file-name-sans-versions | ||
| 1387 | (file-name-sans-extension | ||
| 1388 | (file-name-nondirectory s)))) | ||
| 1389 | s)) sources) | ||
| 1390 | (kill-buffer tmpbuf)))) | ||
| 1391 | |||
| 1392 | ;; Change what was given in the minibuffer to something that can be used to | ||
| 1393 | ;; invoke the debugger. | ||
| 1394 | (defun gud-jdb-massage-args (file args) | ||
| 1395 | ;; The jdb executable must have whitespace between "-classpath" and | ||
| 1396 | ;; it's value while gud-common-init expects all switch values to | ||
| 1397 | ;; follow the switch keyword without intervening whitespace. We | ||
| 1398 | ;; require that when the user enters the "-classpath" switch in the | ||
| 1399 | ;; EMACS minibuffer that they do so without the intervening | ||
| 1400 | ;; whitespace. This function adds it back (it's called after | ||
| 1401 | ;; gud-common-init). There are more switches like this (for | ||
| 1402 | ;; instance "-host" and "-password") but I don't care about them | ||
| 1403 | ;; yet. | ||
| 1404 | (if args | ||
| 1405 | (let (massaged-args user-error) | ||
| 1406 | |||
| 1407 | (while | ||
| 1408 | (and args | ||
| 1409 | (not (string-match "-classpath\\(.+\\)" (car args))) | ||
| 1410 | (not (setq user-error | ||
| 1411 | (string-match "-classpath$" (car args))))) | ||
| 1412 | (setq massaged-args (append massaged-args (list (car args)))) | ||
| 1413 | (setq args (cdr args))) | ||
| 1414 | |||
| 1415 | ;; By this point the current directory is all screwed up. Maybe we | ||
| 1416 | ;; could fix things and re-invoke gud-common-init, but for now I think | ||
| 1417 | ;; issueing the error is good enough. | ||
| 1418 | (if user-error | ||
| 1419 | (progn | ||
| 1420 | (kill-buffer (current-buffer)) | ||
| 1421 | (error "Error: Omit whitespace between '-classpath' and it's value"))) | ||
| 1422 | |||
| 1423 | (if args | ||
| 1424 | (setq massaged-args | ||
| 1425 | (append | ||
| 1426 | massaged-args | ||
| 1427 | (list "-classpath") | ||
| 1428 | (list | ||
| 1429 | (substring | ||
| 1430 | (car args) | ||
| 1431 | (match-beginning 1) (match-end 1))) | ||
| 1432 | (cdr args))) | ||
| 1433 | massaged-args)))) | ||
| 1434 | |||
| 1435 | ;; Search for an association with P, a fully qualified class name, in | ||
| 1436 | ;; gud-jdb-class-source-alist. The asssociation gives the fully | ||
| 1437 | ;; qualified file name of the source file which produced the class. | ||
| 1438 | (defun gud-jdb-find-source-file (p) | ||
| 1439 | (cdr (assoc p gud-jdb-class-source-alist))) | ||
| 1440 | |||
| 1441 | ;; See comentary for other debugger's marker filters - there you will find | ||
| 1442 | ;; important notes about STRING. | ||
| 1443 | (defun gud-jdb-marker-filter (string) | ||
| 1444 | |||
| 1445 | ;; Build up the accumulator. | ||
| 1446 | (setq gud-marker-acc | ||
| 1447 | (if gud-marker-acc | ||
| 1448 | (concat gud-marker-acc string) | ||
| 1449 | string)) | ||
| 1450 | |||
| 1451 | ;; We process STRING from left to right. Each time through the following | ||
| 1452 | ;; loop we process at most one marker. The start variable keeps track of | ||
| 1453 | ;; where we are in the input string through the iterations of this loop. | ||
| 1454 | (let (start file-found) | ||
| 1455 | |||
| 1456 | ;; Process each complete marker in the input. There may be an incomplete | ||
| 1457 | ;; marker at the end of the input string. Incomplete markers are left | ||
| 1458 | ;; in the accumulator for processing the next time the function is called. | ||
| 1459 | (while | ||
| 1460 | |||
| 1461 | ;; Do we see a marker? | ||
| 1462 | (string-match | ||
| 1463 | ;; jdb puts out a string of the following form when it | ||
| 1464 | ;; hits a breakpoint: | ||
| 1465 | ;; | ||
| 1466 | ;; <fully-qualified-class><method> (<class>:<line-number>) | ||
| 1467 | ;; | ||
| 1468 | ;; <fully-qualified-class>'s are composed of Java ID's | ||
| 1469 | ;; separated by periods. <method> and <class> are | ||
| 1470 | ;; also Java ID's. <method> begins with a period and | ||
| 1471 | ;; may contain less-than and greater-than (constructors, | ||
| 1472 | ;; for instance, are called <init> in the symbol table.) | ||
| 1473 | ;; Java ID's begin with a letter followed by letters | ||
| 1474 | ;; and/or digits. The set of letters includes underscore | ||
| 1475 | ;; and dollar sign. | ||
| 1476 | ;; | ||
| 1477 | ;; The first group matches <fully-qualified-class>, | ||
| 1478 | ;; the second group matches <class> and the third group | ||
| 1479 | ;; matches <line-number>. We don't care about using | ||
| 1480 | ;; <method> so we don't "group" it. | ||
| 1481 | ;; | ||
| 1482 | ;; FIXME: Java ID's are UNICODE strings, this matches ASCII | ||
| 1483 | ;; ID's only. | ||
| 1484 | "\\([a-zA-Z0-9.$_]+\\)\\.[a-zA-Z0-9$_<>]+ (\\([a-zA-Z0-9$_]+\\):\\([0-9]+\\))" | ||
| 1485 | gud-marker-acc start) | ||
| 1486 | |||
| 1487 | ;; Figure out the line on which to position the debugging arrow. | ||
| 1488 | ;; Return the info as a cons of the form: | ||
| 1489 | ;; | ||
| 1490 | ;; (<file-name> . <line-number>) . | ||
| 1491 | (if (setq | ||
| 1492 | file-found | ||
| 1493 | (gud-jdb-find-source-file | ||
| 1494 | (substring gud-marker-acc | ||
| 1495 | (match-beginning 1) | ||
| 1496 | (match-end 1)))) | ||
| 1497 | (setq gud-last-frame | ||
| 1498 | (cons | ||
| 1499 | file-found | ||
| 1500 | (string-to-int | ||
| 1501 | (substring gud-marker-acc | ||
| 1502 | (match-beginning 3) | ||
| 1503 | (match-end 3))))) | ||
| 1504 | (message "Could not find source file.")) | ||
| 1505 | |||
| 1506 | ;; Set start after the last character of STRING that we've looked at | ||
| 1507 | ;; and loop to look for another marker. | ||
| 1508 | (setq start (match-end 0)))) | ||
| 1509 | |||
| 1510 | ;; We don't filter any debugger output so just return what we were given. | ||
| 1511 | string) | ||
| 1512 | |||
| 1513 | (defun gud-jdb-find-file (f) | ||
| 1514 | (and (file-readable-p f) | ||
| 1515 | (find-file-noselect f))) | ||
| 1516 | |||
| 1517 | (defvar gud-jdb-command-name "jdb" "Command that executes the Java debugger.") | ||
| 1518 | |||
| 1519 | ;;;###autoload | ||
| 1520 | (defun jdb (command-line) | ||
| 1521 | "Run jdb with command line COMMAND-LINE in a buffer. The buffer is named | ||
| 1522 | \"*gud*\" if no initial class is given or \"*gud-<initial-class-basename>*\" | ||
| 1523 | if there is. If the \"-classpath\" switch is given, omit all whitespace | ||
| 1524 | between it and it's value." | ||
| 1525 | (interactive | ||
| 1526 | (list (read-from-minibuffer "Run jdb (like this): " | ||
| 1527 | (if (consp gud-jdb-history) | ||
| 1528 | (car gud-jdb-history) | ||
| 1529 | (concat gud-jdb-command-name " ")) | ||
| 1530 | nil nil | ||
| 1531 | '(gud-jdb-history . 1)))) | ||
| 1532 | |||
| 1533 | (gud-common-init command-line 'gud-jdb-massage-args | ||
| 1534 | 'gud-jdb-marker-filter 'gud-jdb-find-file) | ||
| 1535 | |||
| 1536 | (gud-def gud-break "stop at %l" "\C-b" "Set breakpoint at current line.") | ||
| 1537 | (gud-def gud-remove "clear %l" "\C-d" "Remove breakpoint at current line") | ||
| 1538 | (gud-def gud-step "step" "\C-s" "Step one source line with display.") | ||
| 1539 | (gud-def gud-next "next" "\C-n" "Step one line (skip functions).") | ||
| 1540 | (gud-def gud-cont "cont" "\C-r" "Continue with display.") | ||
| 1541 | |||
| 1542 | (setq comint-prompt-regexp "^> \|^.+\[[0-9]+\] ") | ||
| 1543 | (setq paragraph-start comint-prompt-regexp) | ||
| 1544 | (run-hooks 'jdb-mode-hook) | ||
| 1545 | |||
| 1546 | ;; Create and bind the class/source association list as well as the source | ||
| 1547 | ;; file list. | ||
| 1548 | (setq | ||
| 1549 | gud-jdb-class-source-alist | ||
| 1550 | (gud-jdb-build-class-source-alist | ||
| 1551 | (setq | ||
| 1552 | gud-jdb-source-files | ||
| 1553 | (gud-jdb-build-source-files-list gud-jdb-directories "\\.java$"))))) | ||
| 1554 | |||
| 1270 | 1555 | ||
| 1271 | ;; | 1556 | ;; |
| 1272 | ;; End of debugger-specific information | 1557 | ;; End of debugger-specific information |