diff options
| author | Karl Heuer | 1998-04-08 19:07:45 +0000 |
|---|---|---|
| committer | Karl Heuer | 1998-04-08 19:07:45 +0000 |
| commit | 35dd3c558f94c5988dbd5cc7fc16af0b66c33df7 (patch) | |
| tree | 2ce17877480b992f8c6dbd850d1b6f84100438f9 | |
| parent | c241bb9cbbd81b6327a511b7fc3e7cd63e432909 (diff) | |
| download | emacs-35dd3c558f94c5988dbd5cc7fc16af0b66c33df7.tar.gz emacs-35dd3c558f94c5988dbd5cc7fc16af0b66c33df7.zip | |
(jdb): Do proper analysis of classes defined in a Java
source. This removes the restriction of one class per file.
(gud-jdb-package-of-file): Removed. Replaced with parsing routines.
(gud-jdb-skip-whitespace): New function.
(gud-jdb-skip-single-line-comment): New function.
(gud-jdb-skip-traditional-or-documentation-comment): New function.
(gud-jdb-skip-whitespace-and-comments): New function.
(gud-jdb-skip-id-ish-thing): New function.
(gud-jdb-skip-string-literal): New function.
(gud-jdb-skip-character-literal): New function.
(gud-jdb-skip-block): New function.
(gud-jdb-analyze-source): New function.
(gud-jdb-build-class-source-alist-for-file): New function.
(gud-jdb-analysis-buffer): New variable.
(gud-jdb-build-class-source-alist): Cleaner at the expense of new
variable.
| -rw-r--r-- | lisp/gud.el | 260 |
1 files changed, 227 insertions, 33 deletions
diff --git a/lisp/gud.el b/lisp/gud.el index 47e111bcfe2..eb71dabd2de 100644 --- a/lisp/gud.el +++ b/lisp/gud.el | |||
| @@ -1316,22 +1316,37 @@ and source-file directory for your debugger." | |||
| 1316 | ;; | 1316 | ;; |
| 1317 | ;; Type M-n to step over the current line and M-s to step into it. That, | 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' | 1318 | ;; along with the JDB 'help' command should get you started. The 'quit' |
| 1319 | ;; JDB command will get out out of the debugger. | 1319 | ;; JDB command will get out out of the debugger. There is some truly |
| 1320 | ;; pathetic JDB documentation available at: | ||
| 1321 | ;; | ||
| 1322 | ;; http://java.sun.com/products/jdk/1.1/debugging/ | ||
| 1320 | ;; | 1323 | ;; |
| 1321 | ;; KNOWN PROBLEMS AND FIXME's: | 1324 | ;; KNOWN PROBLEMS AND FIXME's: |
| 1322 | ;; | 1325 | ;; |
| 1323 | ;; Each source file must contain one and only one class or interface | 1326 | ;; Not sure what happens with inner classes ... haven't tried them. |
| 1324 | ;; definition. | ||
| 1325 | ;; | 1327 | ;; |
| 1326 | ;; Does not grok UNICODE id's. Only ASCII id's are supported. | 1328 | ;; Does not grok UNICODE id's. Only ASCII id's are supported. |
| 1327 | ;; | 1329 | ;; |
| 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 | 1330 | ;; You must not put whitespace between "-classpath" and the path to |
| 1332 | ;; search for java classes even though it is required when invoking jdb | 1331 | ;; search for java classes even though it is required when invoking jdb |
| 1333 | ;; from the command line. See gud-jdb-massage-args for details. | 1332 | ;; from the command line. See gud-jdb-massage-args for details. |
| 1334 | ;; | 1333 | ;; |
| 1334 | ;; If any of the source files in the directories listed in | ||
| 1335 | ;; gud-jdb-directories won't parse you'll have problems. Make sure | ||
| 1336 | ;; every file ending in ".java" in these directories parses without error. | ||
| 1337 | ;; | ||
| 1338 | ;; All the .java files in the directories in gud-jdb-directories are | ||
| 1339 | ;; syntactically analyzed each time gud jdb is invoked. It would be | ||
| 1340 | ;; nice to keep as much information as possible between runs. It would | ||
| 1341 | ;; be really nice to analyze the files only as neccessary (when the | ||
| 1342 | ;; source needs to be displayed.) I'm not sure to what extent the former | ||
| 1343 | ;; can be accomplished and I'm not sure the latter can be done at all | ||
| 1344 | ;; since I don't know of any general way to tell which .class files are | ||
| 1345 | ;; defined by which .java file without analyzing all the .java files. | ||
| 1346 | ;; If anyone knows why JavaSoft didn't put the source file names in | ||
| 1347 | ;; debuggable .class files please clue me in so I find something else | ||
| 1348 | ;; to be spiteful and bitter about. | ||
| 1349 | ;; | ||
| 1335 | ;; ====================================================================== | 1350 | ;; ====================================================================== |
| 1336 | ;; gud jdb variables and functions | 1351 | ;; gud jdb variables and functions |
| 1337 | 1352 | ||
| @@ -1352,42 +1367,221 @@ The file names should be absolute, or relative to the current directory.") | |||
| 1352 | (defun gud-jdb-build-source-files-list (path extn) | 1367 | (defun gud-jdb-build-source-files-list (path extn) |
| 1353 | (apply 'nconc (mapcar (lambda (d) (directory-files d t extn nil)) path))) | 1368 | (apply 'nconc (mapcar (lambda (d) (directory-files d t extn nil)) path))) |
| 1354 | 1369 | ||
| 1355 | ;; Return the package (with trailing period) to which FILE belongs. | 1370 | ;; Move point past whitespace. |
| 1356 | ;; Returns "" if FILE is in the default package. BUF is the name of a | 1371 | (defun gud-jdb-skip-whitespace () |
| 1357 | ;; buffer into which FILE is read so that it can be searched in order | 1372 | (skip-chars-forward " \n\r\t\014")) |
| 1358 | ;; to determine it's package. As a consequence, the contents of BUF | 1373 | |
| 1359 | ;; are erased by this function. | 1374 | ;; Move point past a "// <eol>" type of comment. |
| 1360 | (defun gud-jdb-package-of-file (buf file) | 1375 | (defun gud-jdb-skip-single-line-comment () |
| 1361 | (set-buffer buf) | 1376 | (end-of-line)) |
| 1362 | (insert-file-contents file nil nil nil t) | 1377 | |
| 1363 | ;; FIXME: Java IDs are UNICODE strings - this code does not | 1378 | ;; Move point past a "/* */" or "/** */" type of comment. |
| 1364 | ;; do the right thing! | 1379 | (defun gud-jdb-skip-traditional-or-documentation-comment () |
| 1365 | ;; FIXME: Does not always ignore contents of comments or string literals. | 1380 | (forward-char 2) |
| 1366 | (if (re-search-forward | 1381 | (catch 'break |
| 1367 | "^[ \t]*package[ \t]+\\([a-zA-Z0-9$_\.]+\\)[ \t]*;" nil t) | 1382 | (while (not (eobp)) |
| 1368 | (concat (match-string 1) ".") | 1383 | (if (eq (following-char) ?*) |
| 1369 | "")) | 1384 | (progn |
| 1385 | (forward-char) | ||
| 1386 | (if (not (eobp)) | ||
| 1387 | (if (eq (following-char) ?/) | ||
| 1388 | (progn | ||
| 1389 | (forward-char) | ||
| 1390 | (throw 'break nil))))) | ||
| 1391 | (forward-char))))) | ||
| 1392 | |||
| 1393 | ;; Move point past any number of consecutive whitespace chars and/or comments. | ||
| 1394 | (defun gud-jdb-skip-whitespace-and-comments () | ||
| 1395 | (gud-jdb-skip-whitespace) | ||
| 1396 | (catch 'done | ||
| 1397 | (while t | ||
| 1398 | (cond | ||
| 1399 | ((looking-at "//") | ||
| 1400 | (gud-jdb-skip-single-line-comment) | ||
| 1401 | (gud-jdb-skip-whitespace)) | ||
| 1402 | ((looking-at "/\\*") | ||
| 1403 | (gud-jdb-skip-traditional-or-documentation-comment) | ||
| 1404 | (gud-jdb-skip-whitespace)) | ||
| 1405 | (t (throw 'done nil)))))) | ||
| 1406 | |||
| 1407 | ;; Move point past things that are id-like. The intent is to skip regular | ||
| 1408 | ;; id's, such as class or interface names as well as package and interface | ||
| 1409 | ;; names. | ||
| 1410 | (defun gud-jdb-skip-id-ish-thing () | ||
| 1411 | (skip-chars-forward "^ /\n\r\t\014,;{")) | ||
| 1412 | |||
| 1413 | ;; Move point past a string literal. | ||
| 1414 | (defun gud-jdb-skip-string-literal () | ||
| 1415 | (forward-char) | ||
| 1416 | (while | ||
| 1417 | (progn | ||
| 1418 | (if (eq (following-char) ?\\) | ||
| 1419 | (forward-char 2)) | ||
| 1420 | (not (eq (following-char) ?\042))) | ||
| 1421 | (forward-char)) | ||
| 1422 | (forward-char)) | ||
| 1423 | |||
| 1424 | ;; Move point past a character literal. | ||
| 1425 | (defun gud-jdb-skip-character-literal () | ||
| 1426 | (forward-char) | ||
| 1427 | (while | ||
| 1428 | (progn | ||
| 1429 | (if (eq (following-char) ?\\) | ||
| 1430 | (forward-char 2)) | ||
| 1431 | (not (eq (following-char) ?\'))) | ||
| 1432 | (forward-char)) | ||
| 1433 | (forward-char)) | ||
| 1434 | |||
| 1435 | ;; Move point past the following block. There may be (legal) cruft before | ||
| 1436 | ;; the block's opening brace. There must be a block or it's the end of life | ||
| 1437 | ;; in petticoat junction. | ||
| 1438 | (defun gud-jdb-skip-block () | ||
| 1439 | |||
| 1440 | ;; Find the begining of the block. | ||
| 1441 | (while | ||
| 1442 | (not (eq (following-char) ?{)) | ||
| 1443 | |||
| 1444 | ;; Skip any constructs that can harbor literal block delimiter | ||
| 1445 | ;; characters and/or the delimiters for the constructs themselves. | ||
| 1446 | (cond | ||
| 1447 | ((looking-at "//") | ||
| 1448 | (gud-jdb-skip-single-line-comment)) | ||
| 1449 | ((looking-at "/\\*") | ||
| 1450 | (gud-jdb-skip-traditional-or-documentation-comment)) | ||
| 1451 | ((eq (following-char) ?\042) | ||
| 1452 | (gud-jdb-skip-string-literal)) | ||
| 1453 | ((eq (following-char) ?\') | ||
| 1454 | (gud-jdb-skip-character-literal)) | ||
| 1455 | (t (forward-char)))) | ||
| 1456 | |||
| 1457 | ;; Now at the begining of the block. | ||
| 1458 | (forward-char) | ||
| 1459 | |||
| 1460 | ;; Skip over the body of the block as well as the final brace. | ||
| 1461 | (let ((open-level 1)) | ||
| 1462 | (while (not (eq open-level 0)) | ||
| 1463 | (cond | ||
| 1464 | ((looking-at "//") | ||
| 1465 | (gud-jdb-skip-single-line-comment)) | ||
| 1466 | ((looking-at "/\\*") | ||
| 1467 | (gud-jdb-skip-traditional-or-documentation-comment)) | ||
| 1468 | ((eq (following-char) ?\042) | ||
| 1469 | (gud-jdb-skip-string-literal)) | ||
| 1470 | ((eq (following-char) ?\') | ||
| 1471 | (gud-jdb-skip-character-literal)) | ||
| 1472 | ((eq (following-char) ?{) | ||
| 1473 | (setq open-level (+ open-level 1)) | ||
| 1474 | (forward-char)) | ||
| 1475 | ((eq (following-char) ?}) | ||
| 1476 | (setq open-level (- open-level 1)) | ||
| 1477 | (forward-char)) | ||
| 1478 | (t (forward-char)))))) | ||
| 1479 | |||
| 1480 | ;; Find the package and class definitions in Java source file FILE. Assumes | ||
| 1481 | ;; that FILE contains a legal Java program. BUF is a scratch buffer used | ||
| 1482 | ;; to hold the source during analysis. | ||
| 1483 | (defun gud-jdb-analyze-source (buf file) | ||
| 1484 | (let ((l nil)) | ||
| 1485 | (set-buffer buf) | ||
| 1486 | (insert-file-contents file nil nil nil t) | ||
| 1487 | (goto-char 0) | ||
| 1488 | (catch 'abort | ||
| 1489 | (let ((p "")) | ||
| 1490 | (while (progn | ||
| 1491 | (gud-jdb-skip-whitespace) | ||
| 1492 | (not (eobp))) | ||
| 1493 | (cond | ||
| 1494 | |||
| 1495 | ;; Any number of semi's following a block is legal. Move point | ||
| 1496 | ;; past them. Note that comments and whitespace may be | ||
| 1497 | ;; interspersed as well. | ||
| 1498 | ((eq (following-char) ?\073) | ||
| 1499 | (forward-char)) | ||
| 1500 | |||
| 1501 | ;; Move point past a single line comment. | ||
| 1502 | ((looking-at "//") | ||
| 1503 | (gud-jdb-skip-single-line-comment)) | ||
| 1504 | |||
| 1505 | ;; Move point past a traditional or documentation comment. | ||
| 1506 | ((looking-at "/\\*") | ||
| 1507 | (gud-jdb-skip-traditional-or-documentation-comment)) | ||
| 1508 | |||
| 1509 | ;; Move point past a package statement, but save the PackageName. | ||
| 1510 | ((looking-at "package") | ||
| 1511 | (forward-char 7) | ||
| 1512 | (gud-jdb-skip-whitespace-and-comments) | ||
| 1513 | (let ((s (point))) | ||
| 1514 | (gud-jdb-skip-id-ish-thing) | ||
| 1515 | (setq p (concat (buffer-substring s (point)) ".")) | ||
| 1516 | (gud-jdb-skip-whitespace-and-comments) | ||
| 1517 | (if (eq (following-char) ?\073) | ||
| 1518 | (forward-char)))) | ||
| 1519 | |||
| 1520 | ;; Move point past an import statement. | ||
| 1521 | ((looking-at "import") | ||
| 1522 | (forward-char 6) | ||
| 1523 | (gud-jdb-skip-whitespace-and-comments) | ||
| 1524 | (gud-jdb-skip-id-ish-thing) | ||
| 1525 | (gud-jdb-skip-whitespace-and-comments) | ||
| 1526 | (if (eq (following-char) ?\073) | ||
| 1527 | (forward-char))) | ||
| 1528 | |||
| 1529 | ;; Move point past the various kinds of ClassModifiers. | ||
| 1530 | ((looking-at "public") | ||
| 1531 | (forward-char 6)) | ||
| 1532 | ((looking-at "abstract") | ||
| 1533 | (forward-char 8)) | ||
| 1534 | ((looking-at "final") | ||
| 1535 | (forward-char 5)) | ||
| 1536 | |||
| 1537 | ;; Move point past a ClassDeclaraction, but save the class | ||
| 1538 | ;; Identifier. | ||
| 1539 | ((looking-at "class") | ||
| 1540 | (forward-char 5) | ||
| 1541 | (gud-jdb-skip-whitespace-and-comments) | ||
| 1542 | (let ((s (point))) | ||
| 1543 | (gud-jdb-skip-id-ish-thing) | ||
| 1544 | (setq | ||
| 1545 | l (nconc l (list (concat p (buffer-substring s (point))))))) | ||
| 1546 | (gud-jdb-skip-block)) | ||
| 1547 | |||
| 1548 | ;; Move point past an interface statement. | ||
| 1549 | ((looking-at "interface") | ||
| 1550 | (forward-char 9) | ||
| 1551 | (gud-jdb-skip-block)) | ||
| 1552 | |||
| 1553 | ;; Anything else means the input is invalid. | ||
| 1554 | (t | ||
| 1555 | (message (format "Error parsing file %s." file)) | ||
| 1556 | (throw 'abort nil)))))) | ||
| 1557 | l)) | ||
| 1558 | |||
| 1559 | (defun gud-jdb-build-class-source-alist-for-file (file) | ||
| 1560 | (mapcar | ||
| 1561 | (lambda (c) | ||
| 1562 | (cons c file)) | ||
| 1563 | (gud-jdb-analyze-source gud-jdb-analysis-buffer file))) | ||
| 1370 | 1564 | ||
| 1371 | ;; Association list of fully qualified class names (package + class name) and | 1565 | ;; Association list of fully qualified class names (package + class name) and |
| 1372 | ;; their source files. | 1566 | ;; their source files. |
| 1373 | (defvar gud-jdb-class-source-alist nil) | 1567 | (defvar gud-jdb-class-source-alist nil) |
| 1374 | 1568 | ||
| 1569 | ;; This is used to hold a source file during analysis. | ||
| 1570 | (defvar gud-jdb-analysis-buffer nil) | ||
| 1571 | |||
| 1375 | ;; Return an alist of fully qualified classes and the source files | 1572 | ;; Return an alist of fully qualified classes and the source files |
| 1376 | ;; holding their definitions. SOURCES holds a list of all the source | 1573 | ;; holding their definitions. SOURCES holds a list of all the source |
| 1377 | ;; files to examine. | 1574 | ;; files to examine. |
| 1378 | (defun gud-jdb-build-class-source-alist (sources) | 1575 | (defun gud-jdb-build-class-source-alist (sources) |
| 1379 | (let ((tmpbuf (get-buffer-create "*gud-jdb-scratch*"))) | 1576 | (setq gud-jdb-analysis-buffer (get-buffer-create "*gud-jdb-scratch*")) |
| 1380 | (prog1 | 1577 | (prog1 |
| 1381 | (mapcar | 1578 | (apply |
| 1382 | (lambda (s) | 1579 | 'nconc |
| 1383 | (cons | 1580 | (mapcar |
| 1384 | (concat | 1581 | 'gud-jdb-build-class-source-alist-for-file |
| 1385 | (gud-jdb-package-of-file tmpbuf s) | 1582 | sources)) |
| 1386 | (file-name-sans-versions | 1583 | (kill-buffer gud-jdb-analysis-buffer) |
| 1387 | (file-name-sans-extension | 1584 | (setq gud-jdb-analysis-buffer nil))) |
| 1388 | (file-name-nondirectory s)))) | ||
| 1389 | s)) sources) | ||
| 1390 | (kill-buffer tmpbuf)))) | ||
| 1391 | 1585 | ||
| 1392 | ;; Change what was given in the minibuffer to something that can be used to | 1586 | ;; Change what was given in the minibuffer to something that can be used to |
| 1393 | ;; invoke the debugger. | 1587 | ;; invoke the debugger. |