38436
|
1 ;;; mantemp.el --- create manual template instantiations from g++ 2.7.2 output
|
16878
|
2
|
100908
|
3 ;; Copyright (C) 1996, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
64699
|
4 ;; Free Software Foundation, Inc.
|
16878
|
5
|
|
6 ;; Author: Tom Houlder <thoulder@icor.fr>
|
|
7 ;; Created: 10 Dec 1996
|
|
8 ;; Keywords: g++, templates
|
|
9
|
|
10 ;; This file is part of GNU Emacs.
|
|
11
|
94673
|
12 ;; GNU Emacs is free software: you can redistribute it and/or modify
|
|
13 ;; it under the terms of the GNU General Public License as published by
|
|
14 ;; the Free Software Foundation, either version 3 of the License, or
|
|
15 ;; (at your option) any later version.
|
16878
|
16
|
94673
|
17 ;; GNU Emacs is distributed in the hope that it will be useful,
|
|
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
20 ;; GNU General Public License for more details.
|
16878
|
21
|
|
22 ;; You should have received a copy of the GNU General Public License
|
94673
|
23 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
|
16878
|
24
|
|
25 ;;; Commentary:
|
|
26
|
|
27 ;; The following is a typical error message from g++ using STL (here
|
|
28 ;; with split lines):
|
|
29 ;;
|
|
30 ;; AFile.o(.text+0x2d5): undefined reference to
|
|
31 ;; `vector<double>::begin(void)'
|
|
32 ;; AFile.o(.text+0x2e7): undefined reference to
|
|
33 ;; `vector<double>::insert(double *, unsigned int, double const &)'
|
|
34 ;; AnotherFile.o(.text+0x226b8): undefined reference to
|
|
35 ;; `operator!=(rb_tree<basic_string<char>, pair<basic_string<char>
|
|
36 ;; const, AClass *>, select1st<pair<basic_string<char> const, AClass
|
|
37 ;; *>, basic_string<char> >, less<basic_string<char> > >::iterator
|
|
38 ;; const &, rb_tree<basic_string<char>, pair<basic_string<char>
|
|
39 ;; const, AClass *>, select1st<pair<basic_string<char> const, AClass
|
|
40 ;; *>, basic_string<char> >, less<basic_string<char> > >::iterator
|
|
41 ;; const &)'
|
|
42 ;;
|
|
43 ;; The message means that in the object file AFile.o there is one
|
|
44 ;; uninstantiated template class, vector<double>, and in AnotherFile.o
|
|
45 ;; there is one uninstantiated template function, operator!=(...). To
|
|
46 ;; turn this output into manual template instantiations, copy from the
|
|
47 ;; first name of an objective file (here this is AFile.o) to right
|
|
48 ;; after the very last `'' of the output. Put this in a buffer and
|
16879
|
49 ;; call `mantemp-make-mantemps-buffer' with the point in the buffer.
|
|
50 ;; You can also use `mantemp-make-mantemps-region' directly on the
|
16878
|
51 ;; region if the output is already in Emacs.
|
|
52 ;;
|
|
53 ;; The resulting buffer yields (connect the three output lines above
|
|
54 ;; if you want to try):
|
|
55 ;;
|
|
56 ;; template operator!=(rb_tree<basic_string<char>,
|
|
57 ;; pair<basic_string<char> const, AClass *>,
|
|
58 ;; select1st<pair<basic_string<char> const, AClass *>,
|
|
59 ;; basic_string<char> >, less<basic_string<char> > >::iterator const
|
|
60 ;; &, rb_tree<basic_string<char>, pair<basic_string<char> const,
|
|
61 ;; AClass *>, select1st<pair<basic_string<char> const, AClass *>,
|
|
62 ;; basic_string<char> >, less<basic_string<char> > >::iterator const
|
|
63 ;; &);
|
|
64 ;; template class vector<double>;
|
|
65 ;;
|
|
66 ;; which can be included in your C++ program. However, its probably
|
|
67 ;; better to include the necessary header files in the buffer and
|
|
68 ;; compile it as a stand alone implementation file.
|
16879
|
69 ;;
|
|
70 ;; Sometimes, an uninstantiated template may cause a message like the
|
|
71 ;; following
|
|
72 ;;
|
|
73 ;; main.cc:66: invalid use of undefined type
|
|
74 ;; `struct valarray<double,arrayminusopclass<double,c_array<double> > >'
|
|
75 ;;
|
|
76 ;; Follow the same procedure as above and the line is changed to
|
|
77 ;;
|
|
78 ;; template struct valarray<double,
|
|
79 ;; arrayminusopclass<double,c_array<double> > >;
|
16878
|
80
|
|
81 ;; g++ does not output the templates that are needed by the
|
|
82 ;; uninstantiated templates. Therefore you will often get new error
|
|
83 ;; messages after the first instantiations have been included and you
|
|
84 ;; must repeat the operation.
|
|
85
|
|
86 ;;; Code:
|
|
87
|
|
88 (defun mantemp-remove-comments ()
|
|
89 "Remove g++ comments surrounding each function and member function."
|
|
90 (save-excursion
|
|
91 (goto-char (point-min))
|
|
92 (message "Removing comments")
|
|
93 (while (re-search-forward "^[A-z\.()+0-9: ]*`\\|'.*$" nil t)
|
|
94 (replace-match ""))))
|
|
95
|
|
96 (defun mantemp-remove-memfuncs ()
|
|
97 "Remove member function extensions so that only class names remain."
|
|
98 (save-excursion
|
|
99 ;; Remove conversion operator extensions.
|
|
100 (goto-char (point-min))
|
|
101 (message "Removing member function extensions")
|
|
102 (while (re-search-forward
|
|
103 "^[A-z :&*<>~=,0-9+]*>::operator " nil t nil)
|
|
104 (progn
|
|
105 (backward-char 11)
|
77374
|
106 (delete-region (point) (line-end-position))))
|
16878
|
107 ;; Remove other member function extensions.
|
|
108 (goto-char (point-min))
|
|
109 (message "Removing member function extensions")
|
|
110 (while (re-search-forward "^[A-z :&*<>~=,0-9+]*>::" nil t nil)
|
|
111 (progn
|
|
112 (backward-char 2)
|
77374
|
113 (delete-region (point) (line-end-position))))))
|
16878
|
114
|
|
115 (defun mantemp-sort-and-unique-lines ()
|
|
116 "Eliminate all consecutive duplicate lines in the buffer."
|
|
117 (save-excursion
|
|
118 (message "Sorting")
|
|
119 (sort-regexp-fields nil "^.*$" "\\&"
|
|
120 (point-min)
|
|
121 (point-max))
|
|
122 (goto-char (point-min))
|
|
123 (message "Removing consecutive duplicate lines")
|
|
124 (while (re-search-forward "\\(^.+\\)\n\\1" nil t nil)
|
|
125 (progn
|
|
126 (forward-line -1)
|
|
127 (beginning-of-line)
|
77374
|
128 (delete-region (point) (progn (forward-line 1) (point)))))))
|
16878
|
129
|
|
130 (defun mantemp-insert-cxx-syntax ()
|
|
131 "Insert C++ syntax around each template class and function.
|
|
132 Insert 'template class' for classes, 'template' for
|
|
133 functions and add the statement delimiter `;' at the end of
|
|
134 the lines."
|
|
135 (save-excursion
|
|
136 ;; Insert ';' at the end of each nonempty line.
|
|
137 (goto-char (point-min))
|
|
138 (message "Inserting `;' at the ends")
|
|
139 (while (re-search-forward ".+$" nil t)
|
|
140 (progn
|
|
141 (insert ";")
|
|
142 (if (not (equal (point) (point-max)))
|
|
143 (forward-char))))
|
|
144 ;; We first insert 'template class' at each nonempty line and
|
|
145 ;; subsequently remove 'class' for functions so we don't need to
|
|
146 ;; both scan for classes and functions.
|
|
147 (goto-char (point-min))
|
|
148 (message "Inserting 'template class' for classes")
|
|
149 (while (re-search-forward "^.+" nil t)
|
|
150 (progn
|
|
151 (beginning-of-line)
|
16879
|
152 (if (looking-at "struct[\\t ]+\\|class[\\t ]+")
|
|
153 (insert "template ")
|
|
154 (insert "template class "))))
|
16878
|
155 (goto-char (point-min))
|
|
156 (message "Inserting 'template' for functions")
|
|
157 (while (re-search-forward
|
|
158 "^template class [A-z :&*<>~=,0-9+!]*(" nil t nil)
|
|
159 (progn
|
|
160 (beginning-of-line)
|
|
161 (forward-word 1)
|
77374
|
162 (delete-region (point) (progn (forward-word 1) (point)))))))
|
16878
|
163
|
|
164 (defun mantemp-make-mantemps ()
|
|
165 "Gathering interface to the functions modifying the buffer."
|
|
166 (mantemp-remove-comments)
|
|
167 (mantemp-remove-memfuncs)
|
|
168 (mantemp-sort-and-unique-lines)
|
|
169 (mantemp-insert-cxx-syntax))
|
|
170
|
|
171 (defun mantemp-make-mantemps-buffer ()
|
|
172 "Make manual template instantiations from g++ error messages in the buffer.
|
|
173 Scan the output of g++ describing uninstantiated template
|
|
174 classes and functions and generate the corresponding C++
|
|
175 manual template instantiations. The output is supposed to
|
|
176 have been placed in the current buffer and the current buffer
|
|
177 should otherwise be empty.
|
|
178
|
|
179 See the commentary in file mantemp.el for an example of use."
|
|
180 (interactive)
|
|
181 (mantemp-make-mantemps)
|
16879
|
182 (message "Done"))
|
16878
|
183
|
|
184 (defun mantemp-make-mantemps-region ()
|
|
185 "Make manual template instantiations from g++ error messages in the region.
|
16879
|
186 This function does the same thing as `mantemp-make-mantemps-buffer',
|
|
187 but operates on the region."
|
16878
|
188 (interactive)
|
|
189 (let ((cur-buf (current-buffer))
|
77374
|
190 (mantemp-buffer (generate-new-buffer "*mantemp*"))
|
|
191 (str (buffer-substring (mark) (point))))
|
16878
|
192 ;; Copy the region to a temporary buffer, make the C++ code there
|
|
193 ;; and copy the result back to the current buffer.
|
|
194 (set-buffer mantemp-buffer)
|
77374
|
195 (insert str)
|
16878
|
196 (mantemp-make-mantemps)
|
77374
|
197 (setq str (buffer-string))
|
16878
|
198 (set-buffer cur-buf)
|
77374
|
199 (insert str)
|
16878
|
200 (kill-buffer mantemp-buffer))
|
16879
|
201 (message "Done"))
|
16878
|
202
|
|
203 (provide 'mantemp)
|
|
204
|
93975
|
205 ;; arch-tag: 49794712-3b1b-4baa-9785-39556cb52c94
|
16878
|
206 ;;; mantemp.el ends here
|