1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | #include "clang/Rewrite/Frontend/Rewriters.h" |
15 | #include "clang/Basic/SourceManager.h" |
16 | #include "clang/Lex/Preprocessor.h" |
17 | #include "clang/Rewrite/Core/Rewriter.h" |
18 | #include "llvm/Support/Path.h" |
19 | #include "llvm/Support/raw_ostream.h" |
20 | #include <cstdio> |
21 | #include <memory> |
22 | |
23 | using namespace clang; |
24 | |
25 | |
26 | |
27 | static bool isSameToken(Token &RawTok, Token &PPTok) { |
28 | |
29 | |
30 | if (PPTok.getKind() == RawTok.getKind() && |
31 | PPTok.getIdentifierInfo() == RawTok.getIdentifierInfo()) |
32 | return true; |
33 | |
34 | |
35 | |
36 | |
37 | if (PPTok.getIdentifierInfo() && |
38 | PPTok.getIdentifierInfo() == RawTok.getIdentifierInfo()) |
39 | return true; |
40 | |
41 | return false; |
42 | } |
43 | |
44 | |
45 | |
46 | |
47 | static const Token &(const std::vector<Token> &RawTokens, |
48 | unsigned &CurTok, bool ) { |
49 | (0) . __assert_fail ("CurTok < RawTokens.size() && \"Overran eof!\"", "/home/seafit/code_projects/clang_source/clang/lib/Frontend/Rewrite/RewriteMacros.cpp", 49, __PRETTY_FUNCTION__))" file_link="../../../../include/assert.h.html#88" macro="true">assert(CurTok < RawTokens.size() && "Overran eof!"); |
50 | |
51 | |
52 | if (!ReturnComment && RawTokens[CurTok].is(tok::comment)) |
53 | ++CurTok; |
54 | |
55 | return RawTokens[CurTok++]; |
56 | } |
57 | |
58 | |
59 | |
60 | |
61 | static void LexRawTokensFromMainFile(Preprocessor &PP, |
62 | std::vector<Token> &RawTokens) { |
63 | SourceManager &SM = PP.getSourceManager(); |
64 | |
65 | |
66 | |
67 | const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID()); |
68 | Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOpts()); |
69 | |
70 | |
71 | RawLex.SetCommentRetentionState(true); |
72 | |
73 | Token RawTok; |
74 | do { |
75 | RawLex.LexFromRawLexer(RawTok); |
76 | |
77 | |
78 | |
79 | |
80 | if (RawTok.is(tok::raw_identifier)) |
81 | PP.LookUpIdentifierInfo(RawTok); |
82 | |
83 | RawTokens.push_back(RawTok); |
84 | } while (RawTok.isNot(tok::eof)); |
85 | } |
86 | |
87 | |
88 | |
89 | void clang::RewriteMacrosInInput(Preprocessor &PP, raw_ostream *OS) { |
90 | SourceManager &SM = PP.getSourceManager(); |
91 | |
92 | Rewriter Rewrite; |
93 | Rewrite.setSourceMgr(SM, PP.getLangOpts()); |
94 | RewriteBuffer &RB = Rewrite.getEditBuffer(SM.getMainFileID()); |
95 | |
96 | std::vector<Token> RawTokens; |
97 | LexRawTokensFromMainFile(PP, RawTokens); |
98 | unsigned CurRawTok = 0; |
99 | Token RawTok = GetNextRawTok(RawTokens, CurRawTok, false); |
100 | |
101 | |
102 | |
103 | PP.EnterMainSourceFile(); |
104 | Token PPTok; |
105 | PP.Lex(PPTok); |
106 | |
107 | |
108 | |
109 | |
110 | |
111 | |
112 | |
113 | while (RawTok.isNot(tok::eof) || PPTok.isNot(tok::eof)) { |
114 | SourceLocation PPLoc = SM.getExpansionLoc(PPTok.getLocation()); |
115 | |
116 | |
117 | if (!SM.isWrittenInMainFile(PPLoc)) { |
118 | PP.Lex(PPTok); |
119 | continue; |
120 | } |
121 | |
122 | |
123 | |
124 | |
125 | |
126 | if (RawTok.is(tok::hash) && RawTok.isAtStartOfLine()) { |
127 | |
128 | |
129 | if (RawTokens[CurRawTok].is(tok::identifier)) { |
130 | const IdentifierInfo *II = RawTokens[CurRawTok].getIdentifierInfo(); |
131 | if (II->getName() == "warning") { |
132 | |
133 | RB.InsertTextAfter(SM.getFileOffset(RawTok.getLocation()), "//"); |
134 | } else if (II->getName() == "pragma" && |
135 | RawTokens[CurRawTok+1].is(tok::identifier) && |
136 | (RawTokens[CurRawTok+1].getIdentifierInfo()->getName() == |
137 | "mark")) { |
138 | |
139 | RB.InsertTextAfter(SM.getFileOffset(RawTok.getLocation()), "//"); |
140 | } |
141 | } |
142 | |
143 | |
144 | |
145 | RawTok = GetNextRawTok(RawTokens, CurRawTok, false); |
146 | while (!RawTok.isAtStartOfLine() && RawTok.isNot(tok::eof)) |
147 | RawTok = GetNextRawTok(RawTokens, CurRawTok, false); |
148 | continue; |
149 | } |
150 | |
151 | |
152 | |
153 | unsigned PPOffs = SM.getFileOffset(PPLoc); |
154 | unsigned RawOffs = SM.getFileOffset(RawTok.getLocation()); |
155 | |
156 | |
157 | if (PPOffs == RawOffs && isSameToken(RawTok, PPTok)) { |
158 | RawTok = GetNextRawTok(RawTokens, CurRawTok, false); |
159 | PP.Lex(PPTok); |
160 | continue; |
161 | } |
162 | |
163 | |
164 | |
165 | if (RawOffs <= PPOffs) { |
166 | |
167 | |
168 | bool HasSpace = RawTok.hasLeadingSpace(); |
169 | RB.InsertTextAfter(RawOffs, &" /*"[HasSpace]); |
170 | unsigned EndPos; |
171 | |
172 | do { |
173 | EndPos = RawOffs+RawTok.getLength(); |
174 | |
175 | RawTok = GetNextRawTok(RawTokens, CurRawTok, true); |
176 | RawOffs = SM.getFileOffset(RawTok.getLocation()); |
177 | |
178 | if (RawTok.is(tok::comment)) { |
179 | |
180 | RawTok = GetNextRawTok(RawTokens, CurRawTok, false); |
181 | break; |
182 | } |
183 | |
184 | } while (RawOffs <= PPOffs && !RawTok.isAtStartOfLine() && |
185 | (PPOffs != RawOffs || !isSameToken(RawTok, PPTok))); |
186 | |
187 | RB.InsertTextBefore(EndPos, "*/"); |
188 | continue; |
189 | } |
190 | |
191 | |
192 | |
193 | |
194 | unsigned InsertPos = PPOffs; |
195 | std::string Expansion; |
196 | while (PPOffs < RawOffs) { |
197 | Expansion += ' ' + PP.getSpelling(PPTok); |
198 | PP.Lex(PPTok); |
199 | PPLoc = SM.getExpansionLoc(PPTok.getLocation()); |
200 | PPOffs = SM.getFileOffset(PPLoc); |
201 | } |
202 | Expansion += ' '; |
203 | RB.InsertTextBefore(InsertPos, Expansion); |
204 | } |
205 | |
206 | |
207 | |
208 | if (const RewriteBuffer *RewriteBuf = |
209 | Rewrite.getRewriteBufferFor(SM.getMainFileID())) { |
210 | |
211 | *OS << std::string(RewriteBuf->begin(), RewriteBuf->end()); |
212 | } else { |
213 | fprintf(stderr, "No changes\n"); |
214 | } |
215 | OS->flush(); |
216 | } |
217 | |