blob: 0566d3d91e510d0a3f135badedb6067f2cea1cf3 [file] [log] [blame]
Zonr Changc383a502010-10-12 01:52:08 +08001/*
2 * Copyright 2010, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
zonr6315f762010-10-05 15:35:14 +080017#include "slang_rs_pragma_handler.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070018
Stephen Hines3fd0a942011-01-18 12:27:39 -080019#include <sstream>
Stephen Hinese639eb52010-11-08 19:27:20 -080020#include <string>
21
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070022#include "clang/Basic/TokenKinds.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070023
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070024#include "clang/Lex/LiteralSupport.h"
25#include "clang/Lex/Preprocessor.h"
26#include "clang/Lex/Token.h"
Shih-wei Liao462aefd2010-06-04 15:32:04 -070027
zonr6315f762010-10-05 15:35:14 +080028#include "slang_rs_context.h"
29
Stephen Hinese639eb52010-11-08 19:27:20 -080030namespace slang {
Shih-wei Liao462aefd2010-06-04 15:32:04 -070031
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070032namespace { // Anonymous namespace
33
Shih-wei Liao462aefd2010-06-04 15:32:04 -070034class RSExportTypePragmaHandler : public RSPragmaHandler {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070035 private:
zonr6315f762010-10-05 15:35:14 +080036 void handleItem(const std::string &Item) {
Stephen Hines3fd0a942011-01-18 12:27:39 -080037 mContext->addPragma(this->getName(), Item);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070038 mContext->addExportType(Item);
39 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -070040
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070041 public:
zonr6315f762010-10-05 15:35:14 +080042 RSExportTypePragmaHandler(llvm::StringRef Name, RSContext *Context)
43 : RSPragmaHandler(Name, Context) { return; }
Shih-wei Liao462aefd2010-06-04 15:32:04 -070044
zonr6315f762010-10-05 15:35:14 +080045 void HandlePragma(clang::Preprocessor &PP, clang::Token &FirstToken) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070046 this->handleItemListPragma(PP, FirstToken);
47 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -070048};
49
Shih-wei Liao537446c2010-06-11 16:05:55 -070050class RSJavaPackageNamePragmaHandler : public RSPragmaHandler {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070051 public:
zonr6315f762010-10-05 15:35:14 +080052 RSJavaPackageNamePragmaHandler(llvm::StringRef Name, RSContext *Context)
53 : RSPragmaHandler(Name, Context) { return; }
Shih-wei Liao537446c2010-06-11 16:05:55 -070054
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070055 void HandlePragma(clang::Preprocessor &PP, clang::Token &FirstToken) {
Stephen Hines35f5b392010-11-22 16:39:16 -080056 // FIXME: Need to validate the extracted package name from pragma.
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070057 // Currently "all chars" specified in pragma will be treated as package
58 // name.
59 //
60 // 18.1 The Grammar of the Java Programming Language
61 // (http://java.sun.com/docs/books/jls/third_edition/html/syntax.html#18.1)
62 //
63 // CompilationUnit:
64 // [[Annotations] package QualifiedIdentifier ; ] {ImportDeclaration}
65 // {TypeDeclaration}
66 //
67 // QualifiedIdentifier:
68 // Identifier { . Identifier }
69 //
70 // Identifier:
71 // IDENTIFIER
72 //
73 // 3.8 Identifiers
74 // (http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.8)
75 //
76 //
Shih-wei Liao537446c2010-06-11 16:05:55 -070077
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070078 clang::Token &PragmaToken = FirstToken;
79 std::string PackageName;
Shih-wei Liao537446c2010-06-11 16:05:55 -070080
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070081 // Skip first token, "java_package_name"
82 PP.LexUnexpandedToken(PragmaToken);
Shih-wei Liao537446c2010-06-11 16:05:55 -070083
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070084 // Now, the current token must be clang::tok::lpara
85 if (PragmaToken.isNot(clang::tok::l_paren))
86 return;
Shih-wei Liao537446c2010-06-11 16:05:55 -070087
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070088 while (PragmaToken.isNot(clang::tok::eom)) {
89 // Lex package name
90 PP.LexUnexpandedToken(PragmaToken);
91
92 bool Invalid;
93 std::string Spelling = PP.getSpelling(PragmaToken, &Invalid);
94 if (!Invalid)
95 PackageName.append(Spelling);
96
97 // Pre-mature end (syntax error will be triggered by preprocessor later)
zonr6315f762010-10-05 15:35:14 +080098 if (PragmaToken.is(clang::tok::eom) || PragmaToken.is(clang::tok::eof)) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070099 break;
zonr6315f762010-10-05 15:35:14 +0800100 } else {
Stephen Hines96ab06c2011-01-05 15:29:26 -0800101 // Next token is ')' (end of pragma)
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700102 const clang::Token &NextTok = PP.LookAhead(0);
103 if (NextTok.is(clang::tok::r_paren)) {
Stephen Hines3fd0a942011-01-18 12:27:39 -0800104 mContext->addPragma(this->getName(), PackageName);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700105 mContext->setReflectJavaPackageName(PackageName);
106 // Lex until meets clang::tok::eom
107 do {
Shih-wei Liao537446c2010-06-11 16:05:55 -0700108 PP.LexUnexpandedToken(PragmaToken);
zonr6315f762010-10-05 15:35:14 +0800109 } while (PragmaToken.isNot(clang::tok::eom));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700110 break;
Shih-wei Liao537446c2010-06-11 16:05:55 -0700111 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700112 }
Shih-wei Liao537446c2010-06-11 16:05:55 -0700113 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700114 return;
115 }
Shih-wei Liao537446c2010-06-11 16:05:55 -0700116};
117
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800118class RSReflectLicensePragmaHandler : public RSPragmaHandler {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700119 private:
120 void handleItem(const std::string &Item) {
Stephen Hines3fd0a942011-01-18 12:27:39 -0800121 mContext->addPragma(this->getName(), Item);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700122 mContext->setLicenseNote(Item);
123 }
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800124
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700125 public:
126 RSReflectLicensePragmaHandler(llvm::StringRef Name, RSContext *Context)
127 : RSPragmaHandler(Name, Context) { return; }
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800128
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700129 void HandlePragma(clang::Preprocessor &PP, clang::Token &FirstToken) {
Stephen Hines9d2c0fa2011-01-05 14:55:18 -0800130 this->handleOptionalStringLiteralParamPragma(PP, FirstToken);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700131 }
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800132};
133
Stephen Hines96ab06c2011-01-05 15:29:26 -0800134class RSVersionPragmaHandler : public RSPragmaHandler {
135 private:
136 void handleInt(const int v) {
Stephen Hines3fd0a942011-01-18 12:27:39 -0800137 std::stringstream ss;
138 ss << v;
139 mContext->addPragma(this->getName(), ss.str());
Stephen Hines96ab06c2011-01-05 15:29:26 -0800140 mContext->setVersion(v);
141 }
142
143 public:
144 RSVersionPragmaHandler(llvm::StringRef Name, RSContext *Context)
145 : RSPragmaHandler(Name, Context) { return; }
146
147 void HandlePragma(clang::Preprocessor &PP, clang::Token &FirstToken) {
148 this->handleIntegerParamPragma(PP, FirstToken);
149 }
150};
151
Stephen Hinese639eb52010-11-08 19:27:20 -0800152} // namespace
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700153
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700154RSPragmaHandler *
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700155RSPragmaHandler::CreatePragmaExportTypeHandler(RSContext *Context) {
156 return new RSExportTypePragmaHandler("export_type", Context);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700157}
158
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700159RSPragmaHandler *
160RSPragmaHandler::CreatePragmaJavaPackageNameHandler(RSContext *Context) {
161 return new RSJavaPackageNamePragmaHandler("java_package_name", Context);
Shih-wei Liao537446c2010-06-11 16:05:55 -0700162}
163
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700164RSPragmaHandler *
165RSPragmaHandler::CreatePragmaReflectLicenseHandler(RSContext *Context) {
166 return new RSJavaPackageNamePragmaHandler("set_reflect_license", Context);
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800167}
168
Stephen Hines96ab06c2011-01-05 15:29:26 -0800169RSPragmaHandler *
170RSPragmaHandler::CreatePragmaVersionHandler(RSContext *Context) {
171 return new RSVersionPragmaHandler("version", Context);
172}
173
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700174void RSPragmaHandler::handleItemListPragma(clang::Preprocessor &PP,
175 clang::Token &FirstToken) {
176 clang::Token &PragmaToken = FirstToken;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700177
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700178 // Skip first token, like "export_var"
179 PP.LexUnexpandedToken(PragmaToken);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700180
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700181 // Now, the current token must be clang::tok::lpara
182 if (PragmaToken.isNot(clang::tok::l_paren))
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700183 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700184
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700185 while (PragmaToken.isNot(clang::tok::eom)) {
186 // Lex variable name
187 PP.LexUnexpandedToken(PragmaToken);
188 if (PragmaToken.is(clang::tok::identifier))
zonr6315f762010-10-05 15:35:14 +0800189 this->handleItem(PP.getSpelling(PragmaToken));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700190 else
191 break;
Victor Hsiehc6718b32010-06-23 09:29:44 +0800192
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700193 assert(PragmaToken.isNot(clang::tok::eom));
194
Victor Hsiehc6718b32010-06-23 09:29:44 +0800195 PP.LexUnexpandedToken(PragmaToken);
196
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700197 if (PragmaToken.isNot(clang::tok::comma))
198 break;
199 }
200 return;
201}
202
zonr6315f762010-10-05 15:35:14 +0800203void RSPragmaHandler::handleNonParamPragma(clang::Preprocessor &PP,
204 clang::Token &FirstToken) {
205 clang::Token &PragmaToken = FirstToken;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700206
207 // Skip first token, like "export_var_all"
208 PP.LexUnexpandedToken(PragmaToken);
209
210 // Should be end immediately
211 if (PragmaToken.isNot(clang::tok::eom))
212 fprintf(stderr, "RSPragmaHandler::handleNonParamPragma: "
213 "expected a clang::tok::eom\n");
214 return;
215}
216
Stephen Hines9d2c0fa2011-01-05 14:55:18 -0800217void RSPragmaHandler::handleOptionalStringLiteralParamPragma(
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700218 clang::Preprocessor &PP, clang::Token &FirstToken) {
219 clang::Token &PragmaToken = FirstToken;
220
221 // Skip first token, like "set_reflect_license"
222 PP.LexUnexpandedToken(PragmaToken);
223
224 // Now, the current token must be clang::tok::lpara
225 if (PragmaToken.isNot(clang::tok::l_paren))
Victor Hsiehc6718b32010-06-23 09:29:44 +0800226 return;
Victor Hsiehc6718b32010-06-23 09:29:44 +0800227
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700228 // If not ')', eat the following string literal as the license
229 PP.LexUnexpandedToken(PragmaToken);
230 if (PragmaToken.isNot(clang::tok::r_paren)) {
231 // Eat the whole string literal
232 clang::StringLiteralParser StringLiteral(&PragmaToken, 1, PP);
233 if (StringLiteral.hadError)
Stephen Hines9d2c0fa2011-01-05 14:55:18 -0800234 fprintf(stderr, "RSPragmaHandler::handleOptionalStringLiteralParamPragma"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700235 ": illegal string literal\n");
236 else
zonr6315f762010-10-05 15:35:14 +0800237 this->handleItem(std::string(StringLiteral.GetString()));
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800238
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700239 // The current token should be clang::tok::r_para
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800240 PP.LexUnexpandedToken(PragmaToken);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700241 if (PragmaToken.isNot(clang::tok::r_paren))
Stephen Hines9d2c0fa2011-01-05 14:55:18 -0800242 fprintf(stderr, "RSPragmaHandler::handleOptionalStringLiteralParamPragma"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700243 ": expected a ')'\n");
244 } else {
245 // If no argument, remove the license
zonr6315f762010-10-05 15:35:14 +0800246 this->handleItem("");
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700247 }
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800248}
Stephen Hinese639eb52010-11-08 19:27:20 -0800249
Stephen Hines96ab06c2011-01-05 15:29:26 -0800250void RSPragmaHandler::handleIntegerParamPragma(
251 clang::Preprocessor &PP, clang::Token &FirstToken) {
252 clang::Token &PragmaToken = FirstToken;
253
254 // Skip first token, like "version"
255 PP.LexUnexpandedToken(PragmaToken);
256
257 // Now, the current token must be clang::tok::lpara
258 if (PragmaToken.isNot(clang::tok::l_paren))
259 return;
260 PP.LexUnexpandedToken(PragmaToken);
261
262 if (PragmaToken.is(clang::tok::numeric_constant)) {
263 clang::NumericLiteralParser NumericLiteral(PragmaToken.getLiteralData(),
264 PragmaToken.getLiteralData() + PragmaToken.getLength(),
265 PragmaToken.getLocation(), PP);
266 if (NumericLiteral.hadError) {
267 fprintf(stderr, "RSPragmaHandler::handleIntegerParamPragma"
268 ": illegal numeric literal\n");
269 } else {
270 llvm::APInt Val(32, 0);
271 NumericLiteral.GetIntegerValue(Val);
272 this->handleInt(static_cast<int>(Val.getSExtValue()));
273 }
274 PP.LexUnexpandedToken(PragmaToken);
275 } else {
276 // If no argument, set the version to 0
277 this->handleInt(0);
278 }
279
280 if (PragmaToken.isNot(clang::tok::r_paren)) {
281 fprintf(stderr, "RSPragmaHandler::handleIntegerParamPragma"
282 ": expected a ')'\n");
283 }
284
285 do {
286 PP.LexUnexpandedToken(PragmaToken);
287 } while (PragmaToken.isNot(clang::tok::eom));
288}
289
Stephen Hinese639eb52010-11-08 19:27:20 -0800290} // namespace slang