Commit | Line | Data |
---|---|---|
e8af40ee | 1 | ;;; mantemp.el --- create manual template instantiations from g++ 2.7.2 output |
d20b6dfd | 2 | |
5df4f04c | 3 | ;; Copyright (C) 1996, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 |
034babe1 | 4 | ;; Free Software Foundation, Inc. |
d20b6dfd RS |
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 | ||
b1fc2b50 GM |
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. | |
d20b6dfd | 16 | |
b1fc2b50 GM |
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. | |
d20b6dfd RS |
21 | |
22 | ;; You should have received a copy of the GNU General Public License | |
b1fc2b50 | 23 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. |
d20b6dfd RS |
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 | |
474a797e RS |
49 | ;; call `mantemp-make-mantemps-buffer' with the point in the buffer. |
50 | ;; You can also use `mantemp-make-mantemps-region' directly on the | |
d20b6dfd RS |
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. | |
474a797e RS |
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> > >; | |
d20b6dfd RS |
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) | |
97f67490 | 106 | (delete-region (point) (line-end-position)))) |
d20b6dfd RS |
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) | |
97f67490 | 113 | (delete-region (point) (line-end-position)))))) |
d20b6dfd RS |
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) | |
97f67490 | 128 | (delete-region (point) (progn (forward-line 1) (point))))))) |
d20b6dfd RS |
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) | |
474a797e RS |
152 | (if (looking-at "struct[\\t ]+\\|class[\\t ]+") |
153 | (insert "template ") | |
154 | (insert "template class ")))) | |
d20b6dfd RS |
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) | |
97f67490 | 162 | (delete-region (point) (progn (forward-word 1) (point))))))) |
d20b6dfd RS |
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) | |
474a797e | 182 | (message "Done")) |
d20b6dfd RS |
183 | |
184 | (defun mantemp-make-mantemps-region () | |
185 | "Make manual template instantiations from g++ error messages in the region. | |
474a797e RS |
186 | This function does the same thing as `mantemp-make-mantemps-buffer', |
187 | but operates on the region." | |
d20b6dfd RS |
188 | (interactive) |
189 | (let ((cur-buf (current-buffer)) | |
97f67490 CY |
190 | (mantemp-buffer (generate-new-buffer "*mantemp*")) |
191 | (str (buffer-substring (mark) (point)))) | |
d20b6dfd RS |
192 | ;; Copy the region to a temporary buffer, make the C++ code there |
193 | ;; and copy the result back to the current buffer. | |
d20b6dfd | 194 | (set-buffer mantemp-buffer) |
97f67490 | 195 | (insert str) |
d20b6dfd | 196 | (mantemp-make-mantemps) |
97f67490 | 197 | (setq str (buffer-string)) |
d20b6dfd | 198 | (set-buffer cur-buf) |
97f67490 | 199 | (insert str) |
d20b6dfd | 200 | (kill-buffer mantemp-buffer)) |
474a797e | 201 | (message "Done")) |
d20b6dfd RS |
202 | |
203 | (provide 'mantemp) | |
204 | ||
cbee283d | 205 | ;; arch-tag: 49794712-3b1b-4baa-9785-39556cb52c94 |
d20b6dfd | 206 | ;;; mantemp.el ends here |