1 ;;;;\filename psgml-debug.el
2 ;;;\Last edited: 2001-03-10 00:32:00 lenst
3 ;;;\RCS $Id: psgml-debug.el,v 2.26 2001/12/14 10:26:57 lenst Exp $
4 ;;;\author {Lennart Staflin}
10 (require 'psgml-parse
)
13 (autoload 'sgml-translate-model
"psgml-dtd" "" nil
)
17 (define-key sgml-mode-map
"\C-c," 'sgml-goto-cache
)
18 (define-key sgml-mode-map
"\C-c\C-x" 'sgml-dump-tree
)
19 (define-key sgml-mode-map
"\C-c." 'sgml-shortref-identify
)
21 (defun sgml-this-element ()
23 (let ((tree (sgml-find-element-of (point))))
24 (sgml-dump-rec tree
)))
26 (defun sgml-goto-cache ()
28 (setq sgml-dtd-info
(sgml-pstate-dtd sgml-buffer-parse-state
)
29 sgml-top-tree
(sgml-pstate-top-tree sgml-buffer-parse-state
))
30 (sgml-goto-start-point (point))
31 (message "%s" (sgml-dump-node sgml-current-tree
)))
33 (defun sgml-dump-tree (arg)
37 (with-output-to-temp-buffer "*Dump*"
38 (sgml-dump-rec (sgml-pstate-top-tree sgml-buffer-parse-state
))))
40 (defun sgml-auto-dump ()
41 (let ((standard-output (get-buffer-create "*Dump*"))
42 (cb (current-buffer)))
44 (when sgml-buffer-parse-state
46 (progn (set-buffer standard-output
)
50 (sgml-dump-rec (sgml-pstate-top-tree sgml-buffer-parse-state
))
55 (defun sgml-start-auto-dump ()
57 (add-hook 'post-command-hook
58 (function sgml-auto-dump
)
61 (defun sgml-comepos (epos)
62 (if (sgml-strict-epos-p epos
)
64 (sgml-entity-name (sgml-eref-entity (sgml-epos-eref epos
)))
68 (defun sgml-dump-node (u)
70 "%s%s start:%s(%s) end:%s(%s) epos:%s/%s net:%s\n"
71 (make-string (sgml-tree-level u
) ?.
)
73 (sgml-element-start u
) (sgml-tree-stag-len u
)
74 (if (sgml-tree-etag-epos u
) (sgml-tree-end u
)) (sgml-tree-etag-len u
)
75 (sgml-comepos (sgml-tree-stag-epos u
))
76 (sgml-comepos (sgml-tree-etag-epos u
))
77 (sgml-tree-net-enabled u
)))
79 (defun sgml-dump-rec (u)
81 (princ (sgml-dump-node u
))
82 (sgml-dump-rec (sgml-tree-content u
))
83 (setq u
(sgml-tree-next u
))))
85 (defun sgml-shortref-identify ()
87 (sgml-find-context-of (point))
88 (let* ((nobol (eq (point) sgml-rs-ignore-pos
))
89 (tem (sgml-deref-shortmap sgml-current-shortmap nobol
)))
90 (message "%s (%s)" tem nobol
)))
92 (defun sgml-lookup-shortref-name (table map
)
93 (car (rassq map
(cdr table
))))
95 (defun sgml-show-current-map ()
97 (sgml-find-context-of (point))
98 (let ((name (sgml-lookup-shortref-name
99 (sgml-dtd-shortmaps sgml-dtd-info
)
100 sgml-current-shortmap
)))
101 (message "Current map: %s"
102 (or name
"#EMPTY"))))
106 ;;(put 'when 'edebug-form-hook t)
107 ;;(put 'unless 'edebug-form-hook t)
108 ;;(put 'push 'edebug-form-hook '(form sexp))
109 ;;(put 'setf 'edebug-form-hook '(sexp form))
111 (setq edebug-print-level
3
112 edebug-print-length
5
113 edebug-print-circle nil
117 (unless sgml-running-lucid
118 (def-edebug-spec sgml-with-parser-syntax
(&rest form
))
119 (def-edebug-spec sgml-with-parser-syntax-ro
(&rest form
))
120 (def-edebug-spec sgml-skip-upto
(sexp))
121 (def-edebug-spec sgml-check-delim
(sexp &optional sexp
))
122 (def-edebug-spec sgml-parse-delim
(sexp &optional sexp
))
123 (def-edebug-spec sgml-is-delim
(sexp &optional sexp sexp sexp
))))
127 (defun sgml-dump-dtd (&optional dtd
)
130 (setq dtd
(sgml-pstate-dtd sgml-buffer-parse-state
)))
131 (with-output-to-temp-buffer "*DTD dump*"
132 (princ (format "Dependencies: %S\n"
133 (sgml-dtd-dependencies dtd
)))
134 (loop for et being the symbols of
(sgml-dtd-eltypes dtd
)
135 do
(sgml-dp-element et
))))
137 (defun sgml-dump-element (el-name)
139 (list (completing-read "Element: "
141 (sgml-pstate-dtd sgml-buffer-parse-state
))
143 (with-output-to-temp-buffer "*Element dump*"
144 (sgml-dp-element (sgml-lookup-eltype el-name
))))
146 (defun sgml-dp-element (el)
148 ((sgml-eltype-defined el
)
149 (princ (format "Element %s %s %s%s:\n"
150 (sgml-eltype-name el
)
151 (if (sgml-eltype-stag-optional el
) "O" "-")
152 (if (sgml-eltype-etag-optional el
) "O" "-")
153 (if (sgml-eltype-mixed el
) " mixed" "")))
155 ((sgml-model-group-p (sgml-eltype-model el
))
156 (sgml-dp-model (sgml-eltype-model el
)))
158 (prin1 (sgml-eltype-model el
))
160 (princ (format "Exeptions: +%S -%S\n"
161 (sgml-eltype-includes el
)
162 (sgml-eltype-excludes el
)))
163 (princ (format "Attlist: %S\n" (sgml-eltype-attlist el
)))
164 (princ (format "Plist: %S\n" (symbol-plist el
))))
166 (princ (format "Undefined element %s\n" (sgml-eltype-name el
)))))
170 (defun sgml-dp-model (model &optional indent
)
171 (or indent
(setq indent
0))
172 (let ((sgml-code-xlate (sgml-translate-model model
)))
175 for x in sgml-code-xlate do
176 (cond ((sgml-normal-state-p (car x
))
177 (princ (format "%s%d: opts=%s reqs=%s\n"
178 (make-string indent ?
) i
179 (sgml-untangel-moves (sgml-state-opts (car x
)))
180 (sgml-untangel-moves (sgml-state-reqs (car x
))))))
182 (princ (format "%s%d: and-node next=%d\n"
183 (make-string indent ?
) i
184 (sgml-code-xlate (sgml-and-node-next (car x
)))))
185 (loop for m in
(sgml-and-node-dfas (car x
))
186 do
(sgml-dp-model m
(+ indent
2))))))))
188 (defun sgml-untangel-moves (moves)
190 collect
(list (sgml-move-token m
)
191 (sgml-code-xlate (sgml-move-dest m
)))))
196 (defun sgml-dump-state ()
198 (with-output-to-temp-buffer "*State dump*"
199 (sgml-dp-state sgml-current-state
)))
201 (defun sgml-dp-state (state &optional indent
)
202 (or indent
(setq indent
0))
204 ((sgml-normal-state-p state
)
205 (sgml-dp-model state indent
))
207 (princ (format "%sand-state\n" (make-string indent ?
)))
208 (sgml-dp-state (sgml-and-state-substate state
) (+ 2 indent
))
209 (princ (format "%s--next\n" (make-string indent ?
)))
210 (sgml-dp-state (sgml-and-state-next state
) (+ 2 indent
))
211 (princ (format "%s--dfas\n" (make-string indent ?
)))
212 (loop for m in
(sgml-and-state-dfas state
)
213 do
(sgml-dp-model m
(+ indent
2))
214 (princ (format "%s--\n" (make-string indent ?
)))))))
217 ;;;; Build autoloads for all interactive functions in psgml-parse
219 (defun sgml-build-autoloads ()
221 (with-output-to-temp-buffer "*autoload*"
223 for file in
'("psgml-parse" "psgml-edit" "psgml-dtd"
224 "psgml-info" "psgml-charent")
226 (set-buffer (find-file-noselect (concat file
".el")))
227 (goto-char (point-min))
230 (re-search-forward "^(defun +\\([^ ]+\\)" nil t
))
231 (let ((name (buffer-substring (match-beginning 1)
234 (forward-sexp 1) ; skip argument list
235 (skip-chars-forward " \n\t")
236 (when (eq ?
\" (following-char)) ; doc string
237 (setq doc
(buffer-substring (point)
238 (progn (forward-sexp 1)
240 (skip-chars-forward " \n\t")
241 (when (looking-at "(interactive")
243 (message "No doc for %s" name
))
245 "(autoload '%s \"%s\" %s t)\n"
246 name file doc
))))))))
248 ;;;; Test psgml with sgmls test cases
250 (defun test-sgml (start)
253 (sgml-show-warnings t
))
254 (with-output-to-temp-buffer "*Testing psgml*"
257 (setq file
(format "/ni/src/sgmls-1.1/test/test%03d.sgm"
259 (file-exists-p file
))
260 (princ (format "*** File test%03d ***\n" start
))
262 (condition-case errcode
265 ;;(sgml-next-trouble-spot)
266 (sgml-parse-until-end-of nil
))
270 (if (get-buffer sgml-log-buffer-name
)
271 (princ (save-excursion
272 (set-buffer sgml-log-buffer-name
)
277 (kill-buffer (current-buffer))
278 (setq start
(1+ start
))))))
283 (defun profile-sgml (&optional file
)
285 (or file
(setq file
(expand-file-name "~/work/sigmalink/BBB/config/configspec.xml")))
288 (sgml-instrument-parser)
292 (sgml-reparse-buffer (function sgml-handle-shortref
)))
295 (defun sgml-instrument-parser ()
298 (setq elp-function-list nil
)
300 (setq elp-function-list
304 sgml-parse-markup-declaration
305 sgml-do-processing-instruction
307 sgml-tree-net-enabled
313 sgml-do-general-entity-ref
316 sgml-shortmap-skipstring
318 sgml-parse-attribute-specification-list
322 sgml-list-implications
323 sgml-move-current-state
324 sgml-do-empty-start-tag
326 sgml-startnm-char-next
333 (elp-instrument-list))
336 (defun sgml-instrument-dtd-parser ()
339 (setq elp-function-list nil
)
341 (setq elp-function-list
345 sgml-parse-markup-declaration
346 sgml-check-doctype-body
348 sgml-check-dtd-subset
353 sgml-declare-shortref
355 sgml-parse-parameter-literal
356 sgml-check-element-type
357 sgml-check-primitive-content-token
358 sgml-check-model-group
359 ;; In sgml-check-model-group
372 sgml-do-parameter-entity-ref
374 sgml-make-primitive-content-token
379 sgml-remove-redundant-states-1
381 (elp-instrument-list))
383 ;;;; Structure Viewing and Navigating
387 (defvar show-structure-buffer nil
)
388 (defvar show-structure-positions nil
)
389 (defvar show-structure-source-buffer nil
)
391 (defun show-structure ()
393 (let* ((source (current-buffer))
394 (result (get-buffer-create "*Struct*"))
395 (show-structure-buffer result
))
398 (make-local-variable 'show-structure-positions
)
399 (setq show-structure-positions nil
)
400 (make-local-variable 'show-structure-source-buffer
)
401 (setq show-structure-source-buffer source
)
402 (use-local-map (make-sparse-keymap))
403 (local-set-key "\C-c\C-c" 'show-structure-goto
)
405 (show-element (sgml-top-element))
406 (display-buffer result
)))
409 (defun show-structure-goto ()
412 (let ((pos-pair (assoc (point) show-structure-positions
)))
415 (display-buffer show-structure-source-buffer
))
416 (goto-char (cdr pos-pair
)))))
419 (defun show-struct-element-p (element)
420 (or (and (not (sgml-element-data-p element
))
421 (not (sgml-element-empty element
)))
422 (sgml-element-appdata element
'structure
)))
425 (defun show-element (element)
426 (cond ((show-struct-element-p element
)
427 (let ((gi (sgml-element-gi element
))
428 (level (sgml-element-level element
)))
430 (set-buffer show-structure-buffer
)
433 (push (cons (point) (sgml-element-start element
))
434 show-structure-positions
)
435 (insert (format "%s[%15s] " (make-string (- level
1) ?
) gi
))))
436 (catch 'show-data-stop
437 (show-element-data element
))
438 (sgml-map-content element
#'show-element
))))
440 (defun show-element-data (element)
441 (sgml-map-content element
#'show-element-data
#'show-data
)
442 (throw 'show-data-stop nil
))
444 (defun show-data (data)
446 (set-buffer show-structure-buffer
)
447 (let ((start (point)))
450 (subst-char-in-region start end ?
\n ?
)
451 (when (> (current-column) fill-column
)
452 (move-to-column fill-column
)
453 (delete-region (point) end
)
454 (throw 'show-data-stop nil
))))))
456 ;;;; Show current element type
457 ;; Candidate for C-c C-t
459 (autoload 'sgml-princ-names
"psgml-info")
460 (autoload 'sgml-eltype-refrenced-elements
"psgml-info")
462 (define-key sgml-mode-map
"\C-c\C-t" 'sgml-show-current-element-type
)
464 (defun sgml-show-current-element-type ()
466 (let* ((el (sgml-find-context-of (point)))
467 (et (sgml-element-eltype el
)))
468 (with-output-to-temp-buffer "*Current Element Type*"
469 (princ (format "ELEMENT: %s%s\n" (sgml-eltype-name et
)
470 (let ((help-text (sgml-eltype-appdata et
'help-text
)))
472 (format " -- %s" help-text
)
475 (princ (format "\n Start-tag is %s.\n End-tag is %s.\n"
476 (if (sgml-eltype-stag-optional et
)
477 "optional" "required")
478 (if (sgml-eltype-etag-optional et
)
479 "optional" "required"))))
481 (princ "\nCONTENT: ")
482 (cond ((symbolp (sgml-eltype-model et
)) (princ (sgml-eltype-model et
)))
484 (princ (if (sgml-eltype-mixed et
)
487 (sgml-print-position-in-model el et
(point) sgml-current-state
)
490 (mapcar #'symbol-name
(sgml-eltype-refrenced-elements et
))
492 (let ((incl (sgml-eltype-includes et
))
493 (excl (sgml-eltype-excludes et
)))
495 (princ "\n\nEXCEPTIONS:"))
498 (sgml-princ-names (mapcar #'symbol-name incl
)))
501 (sgml-princ-names (mapcar #'symbol-name excl
))))
503 (princ "\n\nATTRIBUTES:\n")
504 (sgml-print-attlist et
)
506 (let ((s (sgml-eltype-shortmap et
)))
508 (princ (format "\nUSEMAP: %s\n" s
))))
510 (princ "\nOCCURS IN:\n")
511 (let ((occurs-in ()))
513 (function (lambda (cand)
514 (when (memq et
(sgml-eltype-refrenced-elements cand
))
515 (push cand occurs-in
))))
516 (sgml-pstate-dtd sgml-buffer-parse-state
))
517 (sgml-princ-names (mapcar 'sgml-eltype-name
518 (sort occurs-in
(function string-lessp
))))))))
520 (defun sgml-print-attlist (et)
521 (let ((ob (current-buffer)))
522 (set-buffer standard-output
)
525 for attdecl in
(sgml-eltype-attlist et
) do
527 (princ (sgml-attdecl-name attdecl
))
528 (let ((dval (sgml-attdecl-declared-value attdecl
))
529 (defl (sgml-attdecl-default-value attdecl
)))
531 (setq dval
(concat (if (eq (first dval
)
534 (mapconcat (function identity
)
540 (cond ((sgml-default-value-type-p 'FIXED defl
)
541 (setq defl
(format "#FIXED '%s'"
542 (sgml-default-value-attval defl
))))
544 (setq defl
(upcase (format "#%s" defl
))))
546 (setq defl
(format "'%s'"
547 (sgml-default-value-attval defl
)))))
555 (defun sgml-print-position-in-model (element element-type buffer-pos parse-state
)
556 (let ((u (sgml-element-content element
))
558 (while (and u
(>= buffer-pos
(sgml-element-end u
)))
559 (push (sgml-element-gi u
) names
)
560 (setq u
(sgml-element-next u
)))
562 (sgml-princ-names (nreverse names
) " " ", ")
565 (let* ((state parse-state
)
566 (required-seq ; the seq of req el following point
567 (loop for required
= (sgml-required-tokens state
)
568 while
(and required
(null (cdr required
)))
569 collect
(sgml-eltype-name (car required
))
570 do
(setq state
(sgml-get-move state
(car required
)))))
572 (mapcar 'sgml-eltype-name
573 (append (sgml-optional-tokens state
)
574 (sgml-required-tokens state
)))))
580 (mapconcat (lambda (x) x
)
582 (if (sgml-final state
)
584 (sgml-princ-names required-seq
" " ", "))
587 (sgml-princ-names last-alt
" (" " | ")
589 (when (sgml-final state
)
592 ;;;; Adding appdata to element types
593 ;;; Candidate for PI PSGML processing
595 (defvar sgml-psgml-pi-enable-outside-dtd nil
)
597 (defun sgml-eval-psgml-pi ()
599 (let ((sgml-psgml-pi-enable-outside-dtd t
))
600 (sgml-parse-to-here)))
602 (define-key sgml-mode-map
"\e\C-x" 'sgml-eval-psgml-pi
)
604 (defun sgml--pi-element-handler ()
606 (let ((eltype (sgml-lookup-eltype (sgml-parse-name)))
609 (while (setq name
(sgml-parse-name))
610 ;; FIXME: check name not reserved
612 (cond ((sgml-parse-delim "VI")
615 (if (looking-at "['\"]")
617 (read (current-buffer)))))
620 (message "%s = %S" name value
)
621 (setf (sgml-eltype-appdata eltype
(intern (downcase name
))) value
)
625 (defun sgml-do-processing-instruction (in-declaration)
626 (let ((start (point)))
627 (when (and (or in-declaration
628 sgml-psgml-pi-enable-outside-dtd
)
629 (eq ?P
(following-char))
630 (looking-at "PSGML +\\(\\sw+\\) *"))
631 (let* ((command (format "%s" (downcase (match-string 1))))
632 (flag-command (assoc command
633 '(("nofill" . nofill
)
634 ("breakafter" . break-after-stag
)
635 ("breakbefore" . break-before-stag
)
636 ("structure" . structure
)))))
637 (goto-char (match-end 0))
639 (sgml-parse-set-appflag (cdr flag-command
)))
640 ((equal command
"element")
641 (sgml--pi-element-handler))
643 (sgml-log-warning "Unknown processing instruction for PSGML: %s"
646 (sgml-skip-upto "XML-PIC")
647 (sgml-skip-upto "PIC"))
648 (when sgml-pi-function
649 (funcall sgml-pi-function
650 (buffer-substring-no-properties start
(point)))))
652 (sgml-check-delim "XML-PIC")
653 (sgml-check-delim "PIC"))
654 (unless in-declaration
655 (sgml-set-markup-type 'pi
))
658 ;;;; Possible modification to allow setting face on content:
660 (defun sgml-set-face-for (start end type
)
661 (let ((face (cdr (assq type sgml-markup-faces
))))
663 (if (and (null type
) sgml-current-tree
)
664 (setq face
(sgml-element-appdata sgml-current-tree
'face
)))
667 (sgml-use-text-properties
668 (let ((inhibit-read-only t
)
669 (after-change-functions nil
)
670 (before-change-functions nil
)
672 (deactivate-mark nil
))
673 (put-text-property start end
'face face
)
675 (put-text-property (1- end
) end
'rear-nonsticky
'(face)))))
677 (let ((current (overlays-at start
))
681 (cond ((and (null old-overlay
)
683 (eq type
(overlay-get (car current
) 'sgml-type
)))
684 (setq old-overlay
(car current
)))
685 ((overlay-get (car current
) 'sgml-type
)
686 ;;(message "delov: %s" (overlay-get (car current) 'sgml-type))
687 (delete-overlay (car current
))))
688 (setq current
(cdr current
)))
689 (while (< (setq pos
(next-overlay-change pos
))
691 (setq current
(overlays-at pos
))
693 (when (overlay-get (car current
) 'sgml-type
)
694 (delete-overlay (car current
)))
695 (setq current
(cdr current
))))
697 (move-overlay old-overlay start end
)
698 (if (null (overlay-get old-overlay
'face
))
699 (overlay-put old-overlay
'face face
)))
701 (setq old-overlay
(make-overlay start end
))
702 (overlay-put old-overlay
'sgml-type type
)
703 (overlay-put old-overlay
'face face
))))))))
705 ;;;; New Right Button Menu
707 (define-key sgml-mode-map
[S-mouse-3
] 'sgml-right-menu
)
709 (defun sgml-right-menu (event)
710 "Pop up a menu with valid tags and insert the choosen tag.
711 If the variable sgml-balanced-tag-edit is t, also inserts the
712 corresponding end tag. If sgml-leave-point-after-insert is t, the point
713 is left after the inserted tag(s), unless the element has som required
714 content. If sgml-leave-point-after-insert is nil the point is left
715 after the first tag inserted."
717 (let ((end (sgml-mouse-region)))
720 ((eq sgml-markup-type
'start-tag
)
721 (sgml-right-stag-menu event
))
724 (sgml-menu-ask event
(if (or end sgml-balanced-tag-edit
)
729 (sgml-tag-region what
(point) end
))
730 (sgml-balanced-tag-edit
731 (sgml-insert-element what
))
733 (sgml-insert-tag what
))))))))
736 (defun sgml-right-stag-menu (event)
737 (let* ((el (sgml-find-attribute-element))
738 (attrib-menu (ignore-errors (sgml-make-attrib-menu el
))))
740 (let* ((alt-gi (mapcar (function sgml-eltype-name
)
742 (sgml-find-context-of (sgml-element-start el
))
743 (sgml-current-list-of-valid-eltypes))))
746 (loop for gi in alt-gi
747 collect
`(,gi
(sgml-change-element-name ,gi
))))))
748 (sgml-popup-multi-menu
752 ("Edit attributes" (sgml-edit-attributes))
753 ("Normalize" (sgml-normalize-element))
754 ("Fill" (sgml-fill-element
755 (sgml-find-context-of (point))))
756 ("Splice" (sgml-untag-element))
757 ("Fold" (sgml-fold-element)))
764 (defun sgml--empty-is-nil (s)
769 (defun sgml-dl-to-table (border table-width first-col-width
)
770 (interactive "sBoder: \nsTab Width: \nsFist Col Width: \n")
771 (setq border
(sgml--empty-is-nil border
))
772 (setq table-width
(sgml--empty-is-nil table-width
))
773 (setq first-col-width
(sgml--empty-is-nil first-col-width
))
774 (let ((el (sgml-find-element-of (point))))
775 (goto-char (sgml-element-etag-start el
))
776 (let ((end (point-marker)))
777 (goto-char (sgml-element-start el
))
778 (sgml-change-element-name "TABLE")
779 (sgml-insert-attribute "BORDER" border
)
780 (sgml-insert-attribute "WIDTH" table-width
)
781 (while (search-forward "<" end t
)
786 (sgml-change-element-name "TD")
787 (sgml-insert-attribute "WIDTH" first-col-width
))
788 ((looking-at "tr>\\s-*<td")
790 (sgml-insert-attribute "WIDTH" first-col-width
))
792 (sgml-change-element-name "TD")
794 (insert "</tr>")))))))