Updated version: Use emacs & Graphviz to plot data structure
简介: Updated version to translate a C struct into corresponding dot file.
转载请注明出处。
Refer to
http://emacser.com/emacs_graphviz_ds.htm or
http://blog.163.com/vic_kk/blog/static/494705242011526292895/
for orignal infomation.
;; Function used to add fields of struct into a dot file (for Graphviz).;;;;; Dot templates(defconst yyc/dot-head "subgraph cluster_%s { node [shape=record fontsize=12 fontname=Courier style=filled]; color = lightgray; style=filled; label = \"Struct %s\"; edge[color=\"brown\"];" "Header part of dot file.")(defconst yyc/dot-tail "}" "Tail part of dot")(defconst yyc/dot-node-head " node_%s[shape=record label=\"<f0>*** STRUCT %s ***|\\" "Format of node.")(defconst yyc/dot-node-tail "\"];" "Format of node.")(defconst attr_str "<f%d>+%s : %s\\l|\\" "nil")(defconst attr_func "<f%d>-%s() : %s\\l|\\" "nil");;;;; Regular expressions to match a field of a struct.(defconst r_attr_str "[ \t]+\\(.*+\\)[ \t]+\\(.*?\\);\\([ \t]*/[/\\*].]*\\)?$" "Regular expression for matching struct fields.")(defconst r_name "\\_<\\(typedef[ \t]+\\)?struct[ \t]+\\(.*\\)?[ \t]*" "Regular expression for mating struct name")(defconst r_func_l "\(.*" "Regular expression to match a function")(defconst r_func_r ".*\)" "Regular expression to match a function")(defconst r_comments "^[ \t/\\*][/\\*]+" "Regular expression to match a commentted field.")(defconst r_struct_func "^[ \t]*\\(.+?\\)[ \t]*\(\\*\\(.*?\\)\)[ \t]*(\\(?:.\\|\\)*?);" "Regular expression to match a function decleration in a struct.")(defconst r_match_semicol (rx (+? anything) ";"))(defconst r_match_attr (rx (+? (not (any "(" ")" "{" "}"))) ";"))(defconst r_match_func (rx (+? (or alnum "_" blank)) "(*" (+? (or alnum "_")) ")" (zero-or-more blank) "(" (*? anything) ");"))(defconst r_match_tag (rx (zero-or-more blank) (zero-or-one "typedef" (one-or-more blank)) "struct" (zero-or-more (or alnum "_" blank)) (zero-or-one "") (zero-or-more blank) "{"))(defun get_struct_tag (decleration) "Abstract decleration from a string" (if (string-match r_name decleration 0) (car (split-string (match-string 2 decleration) "{")) nil))(defun skip(msg x) (if x (message (format "Skip invalid syntax for function: %s." msg)) (message (format "Skip invalid syntax for struct field: %s." msg)) ))(defun yyc/datastruct-to-dot (start end) "Translate a C struct into dot file which can be turned into images using graphviz." (interactive "rp") (let* ((tmp_str "") (var-name "") (var-type "") (counter 0) (next-begin 0) (pos-cur 0) (struct-name "") (header-str "") (pos-end 0) (var-defination (buffer-substring-no-properties start end)) (item_str "") ) (defun iter (pos) (if (string-match r_match_tag var-defination pos) ;; Declerad a struct (progn (setq pos-end (match-end 0)) (setq item_str (substring var-defination pos pos-end)) (setq struct-name (get_struct_tag item_str)) (setq header-str (format yyc/dot-head struct-name struct-name)) (setq tmp_str (format yyc/dot-node-head struct-name struct-name)) (setq pos-cur (1+ pos-end)) (iter pos-cur)) (progn (if (string-match r_match_semicol var-defination pos) (progn (setq pos-end (match-end 0)) (setq item_str (substring var-defination pos pos-end)) (if (string-match r_match_func item_str 0) ;; Function (progn (if (string-match r_struct_func item_str 0) (progn (setq var-type (match-string 1 item_str)) (setq var-name (match-string 2 item_str)) (setq next-begin (match-end 0)) (if (string-match r_comments var-type 0) ;Comments nil (progn (setq counter (+ counter 1)) (setq tmp_str (concat tmp_str (format attr_func counter var-name var-type)))))) (skip item_str t) ) ) (progn (if (equal (string-match r_match_attr item_str 0) 0) (progn (if (string-match r_attr_str item_str 0) (progn (setq var-type (match-string 1 item_str)) (setq var-name (match-string 2 item_str)) (if (string-match r_comments var-type 0) nil (progn (setq counter (+ counter 1)) (setq tmp_str (concat tmp_str (format attr_str counter var-name var-type)))))) (skip item_str nil))) (skip item_str nil)))) (iter pos-end)))))) (save-excursion (iter 0) (set-buffer (get-buffer-create "tmp.dot")) (graphviz-dot-mode) (goto-char (point-max)) (insert header-str tmp_str ) (goto-char (point-max)) (delete-char -1) (insert "<f999>\\"yyc/dot-node-tail yyc/dot-tail) ) (if (one-window-p) (split-window-vertically)) (switch-to-buffer-other-window "tmp.dot") (goto-char (point-min)) ) (message "Finished, please refer to *tmp.dot* buffer.")) |

浙公网安备 33010602011771号