Added missing c++.el
g0dil [Thu, 12 Oct 2006 07:51:22 +0000 (07:51 +0000)]
cc-ide/c++.el [new file with mode: 0644]

diff --git a/cc-ide/c++.el b/cc-ide/c++.el
new file mode 100644 (file)
index 0000000..bda95c9
--- /dev/null
@@ -0,0 +1,341 @@
+; Problem with this RE: a) If the line before the function declaration
+; is a preprocessor directive (like a #define) ending in one or more
+; c++ type keywords they will get included into the type spec.  b) if
+; you define a symbol like #define _const const the expression won't
+; work at all
+
+; Another possible regexp for c++-simple-type-regexp is "^.+". This
+; will make any text before the name of the function but in the same
+; line be the type of the function. Problem: Type cannot span multiple
+; lines.
+
+(defvar c++-prefixes '("__inline__" "static"))
+
+(defconst c++-simple-type-regexp "\\(\\([ \t\n\r]+\\(inline\\|explicit\\|unsigned\\|signed\\|short\\|long\\|const\\|static\\|friend\\)\\)*[ \t\n\r]+[a-zA-Z0-9_]+\\(<[a-zA-Z0-9_, \t\n\t]*>\\)?\\([ \t\n\r]+\\(const[ \t\n\r]+\\)\\)?\\([*&]\\|\\[[ \t\n\r]*[0-9]+[ \t\n\r]*\\]\\)*\\([ \t\n\r]+const\\)?\\)[ \t\n\r]*"
+  "*The RE for a simple type in C++ that is types that neither involve
+  blocks nor functions")
+
+(defconst c++-function-regexp "[^a-zA-Z0-9_:]\\(\\([a-zA-Z0-9_]+\\(<[a-zA-Z0-9_, \t\n\r]*>\\)?::\\)*\\(\\(operator[ \t\n\r]*\\([-+*/.&^|=]\\|++\\|--\\|&&\\|||\\|new\\|delete\\|()\\|\\[\\]\\|->\\|[^();{}]+\\)=?\\)\\|~?[a-zA-Z0-e9_]+\\)\\)[ \t\n\r]*"
+  "The RE for a function definition or declaration")
+
+(defconst c++-class-regexp "\\(class\\|namespace\\)[ \t\n\r]+\\([a-zA-Z0-9_:]+\\)\\([ \t\n\r]*:\\([ \t\n\r]*\\(public\\|protected\\|private\\)?[ \t\n\r]*\\([a-zA-Z0-9_]+\\(<[^>]*>\\)?\\(::\\)?\\)*[ \t\n\r]*,?\\)*\\)?[ \t\n\r]*"
+  "The RE for a class declaration")
+
+(defconst c++-template-regexp "template[ \t\n\r]*<\\([^>]*\\)>[ \t\n\r]*"
+  "The RE for matching template clauses.")
+
+(defconst c++-function-keywords 
+  '( "if" "while" "for" "repeat" "class" "struct" "union" "switch" )
+  "C++ Keywords which may introduce a block")
+
+(defconst c++-keywords 
+  '( "if" "while" "for" "repeat" "class" "struct" "union" "typedef"
+     "char" "int" "float" "double" "signed" "unsigned" "long" "const"
+     "switch" "case" "repeat" "until" "do" "class" "public"
+     "protected" "private" "friend" "operator" "void" "static" "explicit" )
+  "C++ keywords")
+
+(defvar c++-smart-wrap-column 80)
+
+(require 'cc-cmds)
+(require 'cc-engine)
+
+(defun c++-scan-type-backward ()
+  "Scans backward to find the longest valid simple type ending at POINT.
+Assumes POINT is at the end of a C++ simple type expression. 
+Leaves POINT at the beginning of the type expression and returns 
+ ( TYPE-START . TYPE-END )"
+  (save-excursion
+    (let ((end (point))
+         start)
+      (re-search-backward c++-simple-type-regexp 'nil 't)
+      (catch 'exit
+       (while (and (re-search-forward c++-simple-type-regexp end 't)
+                   (< (abs (- end (match-end 0))) 2))
+         (goto-char (match-beginning 0))
+         (setq start (point))
+         (if (not (re-search-backward c++-simple-type-regexp 'nil 't)) 
+             (throw 'exit))))
+      (if start
+          (progn
+           (goto-char start)
+            (skip-chars-forward " \t\n\r")
+           (setq start (point))
+            (goto-char end)
+            (skip-chars-backward " \t\n\r" start)
+           (cons start (point)))
+       'nil ))))
+
+(defun c++-get-function ()
+  "Get the last function declared or called at or after POINT.
+Returns a list 
+        ( ( DECL-START . DECL-END ) 
+          ( TYPE-START . TYPE-END ) 
+         ( NAME-START . NAME_END ) 
+         ( ARGLIST-START . ARGLIST-END )
+          ( FLAGS-START . FLAGS-END ) )"
+  (save-excursion
+    (if (re-search-backward (concat c++-function-regexp "(") 'nil 'true)
+       (goto-char (match-end 0)))
+    (if (re-search-forward (concat c++-function-regexp "(") 'nil 't)
+       (let (type name arglist flags)
+         (setq name (cons (match-beginning 1) (match-end 1)))
+         (goto-char (1- (match-end 0)))
+         (setq arglist (cons (point) 'nil))
+         (if (condition-case nil
+                 (progn (forward-list 1) t)
+               (scan-error nil))
+             (progn
+               (setcdr arglist (point))
+               (if (looking-at "\\([ \t\n\r]*\\(const\\|throw[ \t\n\r]*([^();{}]*)\\|__throw__[ \t\n\t]*(([^();{}]*))\\)\\)*")
+                   (progn
+                     (setq flags (cons (match-beginning 0) (match-end 0)))
+                     (goto-char (match-end 0)))
+                 (setq flags (cons (cdr arglist) (cdr arglist))))
+               (if (looking-at "[ \t\n\r]*:[^;{]*")
+                   (goto-char (match-end 0)))
+               (if (looking-at "[ \t\n\r]*[{;]")
+                   (progn
+                     (goto-char (car name))
+                     (setq type (c++-scan-type-backward))
+                     (if (not type) (setq type (cons (car name) (car name))))
+                     (list (cons (car type) (cdr flags)) type name arglist flags)))))))))
+
+(defun c++-get-function-defn ()
+  "Get the function defined at POINT.
+Returns a list 
+       ( ( DECL-START . DECL-END ) 
+         ( TYPE-START . TYPE-END ) 
+         ( NAME-START . NAME_END ) 
+         ( ARGLIST-START . ARGLIST-END ) 
+          ( FLAGS-START . FLAGS-END )
+         ( BODY-START . BODY-END) )"
+  (save-excursion
+    (let (body fn end)
+      (while (not fn)
+       (if (condition-case nil 
+               (progn (up-list -1) t) 
+             (error (setq fn t) nil))
+           (save-excursion
+             (setq body (cons (point) (save-excursion 
+                                        (forward-list 1) 
+                                        (point))))
+             (save-excursion
+               (while (condition-case nil
+                          (progn 
+                            (up-list -1) 
+                            (setq end (point))
+                            t)
+                        (scan-error nil))))
+             (while (re-search-backward (concat c++-function-regexp "(") end t)
+               (let ((tryfn (c++-get-function)))
+                 (if tryfn
+                     (save-excursion
+                       (goto-char (cdar tryfn))
+                       (if (and (looking-at "[ \t\n\r]*\\(:[^;{]*\\)?{")
+                                (eq (1- (match-end 0)) (car body)))
+                           (progn
+                             (if (match-beginning 1)
+                                 (setcar body (match-beginning 1)))
+                             (setq fn tryfn))))))))))
+      (if (eq fn t)
+         nil
+       (nconc fn (list body))))))
+
+(defun c++-get-classname ()
+  "Get classname which is active at POINT"
+  (let (class
+       (re 't))
+    (save-excursion
+      (while re
+       (if (and (condition-case nil 
+                    (progn (up-list -1) 't) 
+                  (error (setq re 'nil)))
+                (re-search-backward  (concat c++-class-regexp "\\=") 'nil 't))
+           (setq class (concat (match-string 2)
+                               (if class "::" "")
+                               class )))))
+    class))
+
+(defun c++-get-current-class-prefix ()
+  "Get the class prefix currently active at POINT.
+If within a class decl, returns that class name (nested classes
+are supported). If within a function definition at global level,
+returns the class prefix of this function. Returns 'nil if no
+class prefix can be found"
+  (let ((x (c++-get-classname)))
+    (if x
+       x
+      (let ((x (or (c++-get-function-defn)
+                  (c++-get-function))))
+       (if x
+           (save-excursion
+             (goto-char (car (nth 2 x)))
+             (if (re-search-forward "\\=\\([a-zA-Z_0-9]+::\\)+")
+                 (buffer-substring (match-beginning 0) (- (match-end 0) 2))
+               'nil))
+         'nil)))))
+           
+(defun c++-split-template-arg (arg)
+  "Split ARG, a template argument list, and return list of arg names."
+  (let ((raw-args (split-string arg "[ \t\n\r]*,[ \t\n\r]")))
+    (loop for raw-arg in raw-args
+         if (string-match "[a-zA-Z0-9_-]+$" raw-arg)
+           collect (match-string 0 raw-arg)
+         else
+           collect raw-arg)))
+
+(defun c++-get-classname-with-templates ()
+  (let (classname template-args
+       (re 't))
+    (save-excursion
+      (while re
+       (if (and (condition-case nil 
+                    (progn (up-list -1) 't) 
+                  (error (setq re 'nil)))
+                (re-search-backward  (concat c++-class-regexp "\\=") nil t))
+           (let ((template-suffix "")
+                 (class (match-string 2)))
+             (if (re-search-backward (concat c++-template-regexp "\\=") nil t)
+                 (let* ((s (match-string 1))
+                        (args (c++-split-template-arg s))
+                        (raw-args (split-string s "[ \t\n\r]*,[ \t\n\r]")))
+                   (setq template-suffix
+                         (concat "<" (mapconcat 'identity args ",") ">"))
+                   (loop for arg in raw-args
+                         if (not (member arg template-args))
+                           do (setq template-args
+                                    (nconc template-args (list arg))))))
+             (setq classname (concat class
+                                     template-suffix
+                                     (if classname "::" "")
+                                     classname))))))
+    (and classname
+        (cons classname
+              (and template-args
+                   (mapconcat 'identity template-args ", "))))))
+
+(defun c++-get-current-class-prefix-with-templates ()
+  "Get the class prefix currently active at POINT.
+If within a class decl, returns that class name (nested classes
+are supported). If within a function definition at global level,
+returns the class prefix of this function. Returns 'nil if no
+class prefix can be found"
+  (let ((x (c++-get-classname-with-templates)))
+    (if x
+       (car x)
+      (let ((x (or (c++-get-function-defn)
+                  (c++-get-function))))
+       (if x
+           (save-excursion
+             (goto-char (car (nth 2 x)))
+             (if (re-search-forward "\\=\\([a-zA-Z_0-9]+\\(<[a-zA-Z0-9_, \t\n\r]*>\\)?::\\)+")
+                 (buffer-substring (match-beginning 0) (- (match-end 0) 2))
+               'nil))
+         'nil)))))
+
+(defun c++-grab-inline-decl ()
+  "Grab the inline declaration at POINT and change it into a standard
+declaration.  This function deletes the declaration found at POINT and
+places the new declaration into the top of the kill ring"
+  (interactive)
+  (let ((fn (c++-get-function-defn))
+       (class (c++-get-classname-with-templates)))
+    (if (and fn class)
+       (progn
+         (kill-new (concat (if (cdr class)
+                               (concat "template <" (cdr class) ">\n")
+                             "")
+                           "inline "
+                           (buffer-substring (car (nth 0 fn)) (car (nth 2 fn)))
+                           (car class) "::"
+                           (buffer-substring (car (nth 2 fn)) (cdr (nth 5 fn)))
+                           "\n"))
+         (delete-region (cdr (nth 4 fn)) (cdr (nth 5 fn)))
+         (goto-char (cdr (nth 4 fn)))
+         (insert ";")
+         (delete-blank-lines))
+      (if (interactive-p) 
+         (message "Not inside inline function definition body")))))
+
+(defun c++-insert-class-prefix ()
+  "Insert the current class prefix at POINT.
+See also c++-get-current-class-prefix"
+  (interactive)
+  (let ((x (c++-get-current-class-prefix-with-templates)))
+    (if x
+       (insert x "::")
+      (message "Not in scope of any class"))))
+
+(defun c++-next-user-symbol ()
+  "Move POINT to next non-keyword symbol."
+  (interactive)
+  (let (pos)
+    (if (looking-at "[a-zA-Z_:]+")
+       (setq pos (re-search-forward "[a-zA-Z_:]+" 'nil 't)))
+    (while (and (setq pos (re-search-forward "[a-zA-Z_:]*[a-zA-Z_]" 'nil 't))
+               (or (member (match-string 0) c++-keywords)
+                   (c-in-literal))))
+    (goto-char pos)))
+
+(defun c++-previous-user-symbol ()
+  "Move POINT to previous non-keyword symbol."
+  (interactive)  
+  (while (and (re-search-backward "[a-zA-Z_]" 'nil 't)
+             (progn (skip-chars-backward "a-zA-Z_:") 
+                    (or (member (buffer-substring (point) (match-end 0)) 
+                                c++-keywords)
+                        (c-in-literal))))))
+
+(defun c++-next-function-call ()
+  "Move POINT to next function call"
+  (interactive)
+  (let ((start (point))
+       fn)
+    (while (and (setq fn (c++-get-function))
+               (or (>= start (car (nth 0 fn)))
+                   (member (buffer-substring (car (nth 2 fn)) (cdr (nth 2 fn)))
+                           c++-function-keywords)
+                   (/= (car (nth 1 fn)) (car (nth 2 fn)))))                
+      (goto-char (cdr (nth 0 fn)))
+      (re-search-forward "{;" 'nil 't))
+    (goto-char (if fn (car (nth 0 fn)) start))))
+    
+(defun c++-next-function-definition ()
+  "Move POINT to the next function definition or declaration"
+  (interactive)
+  (let ((start (point))
+       fn)
+    (while (and (setq fn (c++-get-function))
+               (or (>= start (car (nth 0 fn)))
+                   (member (buffer-substring (car (nth 2 fn)) (cdr (nth 2 fn)))
+                           c++-function-keywords)
+                   (= (car (nth 1 fn)) (car (nth 2 fn)))))                 
+      (goto-char (cdr (nth 0 fn)))
+      (re-search-forward "[{;]" 'nil 't))
+    (goto-char (if fn (car (nth 0 fn)) start))))
+  
+(defun c++-smart-yank ()
+  "Yank-pop top of kill ring and reformat the yanked object."
+  (interactive)
+  (push-mark)
+  (let ((text (current-kill 0))
+       end-mark line-start)
+    (save-excursion
+      (insert text)
+      (setq end-mark (point-marker)))
+    (while (< (point) (marker-position end-mark))
+      (beginning-of-line)
+      (c-indent-command)
+      (setq line-start (point))
+      (end-of-line)
+      (if (> (current-column) c++-smart-wrap-column)
+         (progn
+           (move-to-column c++-smart-wrap-column)
+           (if (search-backward ",")
+               (progn
+                 (forward-char 1)
+                 (open-line 1)))))
+      (forward-line 1))))
+
+(provide 'c++)