blob: 077ddab0f357ef82ab975705f69a32f850dbb131 [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
Stephen Hines6e6578a2011-02-07 18:05:48 -080028#include "slang_assert.h"
zonr6315f762010-10-05 15:35:14 +080029#include "slang_rs_context.h"
30
Stephen Hinese639eb52010-11-08 19:27:20 -080031namespace slang {
Shih-wei Liao462aefd2010-06-04 15:32:04 -070032
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070033namespace { // Anonymous namespace
34
Shih-wei Liao462aefd2010-06-04 15:32:04 -070035class RSExportTypePragmaHandler : public RSPragmaHandler {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070036 private:
zonr6315f762010-10-05 15:35:14 +080037 void handleItem(const std::string &Item) {
Stephen Hines3fd0a942011-01-18 12:27:39 -080038 mContext->addPragma(this->getName(), Item);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070039 mContext->addExportType(Item);
40 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -070041
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070042 public:
zonr6315f762010-10-05 15:35:14 +080043 RSExportTypePragmaHandler(llvm::StringRef Name, RSContext *Context)
44 : RSPragmaHandler(Name, Context) { return; }
Shih-wei Liao462aefd2010-06-04 15:32:04 -070045
Shih-wei Liaodf5bcce2011-02-28 18:39:23 -080046 void HandlePragma(clang::Preprocessor &PP,
47 clang::PragmaIntroducerKind Introducer,
48 clang::Token &FirstToken) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070049 this->handleItemListPragma(PP, FirstToken);
50 }
Shih-wei Liao462aefd2010-06-04 15:32:04 -070051};
52
Shih-wei Liao537446c2010-06-11 16:05:55 -070053class RSJavaPackageNamePragmaHandler : public RSPragmaHandler {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070054 public:
zonr6315f762010-10-05 15:35:14 +080055 RSJavaPackageNamePragmaHandler(llvm::StringRef Name, RSContext *Context)
56 : RSPragmaHandler(Name, Context) { return; }
Shih-wei Liao537446c2010-06-11 16:05:55 -070057
Shih-wei Liaodf5bcce2011-02-28 18:39:23 -080058 void HandlePragma(clang::Preprocessor &PP,
59 clang::PragmaIntroducerKind Introducer,
60 clang::Token &FirstToken) {
Stephen Hines35f5b392010-11-22 16:39:16 -080061 // FIXME: Need to validate the extracted package name from pragma.
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070062 // Currently "all chars" specified in pragma will be treated as package
63 // name.
64 //
65 // 18.1 The Grammar of the Java Programming Language
66 // (http://java.sun.com/docs/books/jls/third_edition/html/syntax.html#18.1)
67 //
68 // CompilationUnit:
69 // [[Annotations] package QualifiedIdentifier ; ] {ImportDeclaration}
70 // {TypeDeclaration}
71 //
72 // QualifiedIdentifier:
73 // Identifier { . Identifier }
74 //
75 // Identifier:
76 // IDENTIFIER
77 //
78 // 3.8 Identifiers
79 // (http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.8)
80 //
81 //
Shih-wei Liao537446c2010-06-11 16:05:55 -070082
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070083 clang::Token &PragmaToken = FirstToken;
84 std::string PackageName;
Shih-wei Liao537446c2010-06-11 16:05:55 -070085
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070086 // Skip first token, "java_package_name"
87 PP.LexUnexpandedToken(PragmaToken);
Shih-wei Liao537446c2010-06-11 16:05:55 -070088
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070089 // Now, the current token must be clang::tok::lpara
90 if (PragmaToken.isNot(clang::tok::l_paren))
91 return;
Shih-wei Liao537446c2010-06-11 16:05:55 -070092
Loganbe274822011-02-16 22:02:54 +080093 while (PragmaToken.isNot(clang::tok::eod)) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -070094 // Lex package name
95 PP.LexUnexpandedToken(PragmaToken);
96
97 bool Invalid;
98 std::string Spelling = PP.getSpelling(PragmaToken, &Invalid);
99 if (!Invalid)
100 PackageName.append(Spelling);
101
102 // Pre-mature end (syntax error will be triggered by preprocessor later)
Loganbe274822011-02-16 22:02:54 +0800103 if (PragmaToken.is(clang::tok::eod) || PragmaToken.is(clang::tok::eof)) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700104 break;
zonr6315f762010-10-05 15:35:14 +0800105 } else {
Stephen Hines96ab06c2011-01-05 15:29:26 -0800106 // Next token is ')' (end of pragma)
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700107 const clang::Token &NextTok = PP.LookAhead(0);
108 if (NextTok.is(clang::tok::r_paren)) {
Stephen Hines3fd0a942011-01-18 12:27:39 -0800109 mContext->addPragma(this->getName(), PackageName);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700110 mContext->setReflectJavaPackageName(PackageName);
Loganbe274822011-02-16 22:02:54 +0800111 // Lex until meets clang::tok::eod
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700112 do {
Shih-wei Liao537446c2010-06-11 16:05:55 -0700113 PP.LexUnexpandedToken(PragmaToken);
Loganbe274822011-02-16 22:02:54 +0800114 } while (PragmaToken.isNot(clang::tok::eod));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700115 break;
Shih-wei Liao537446c2010-06-11 16:05:55 -0700116 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700117 }
Shih-wei Liao537446c2010-06-11 16:05:55 -0700118 }
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700119 return;
120 }
Shih-wei Liao537446c2010-06-11 16:05:55 -0700121};
122
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800123class RSReflectLicensePragmaHandler : public RSPragmaHandler {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700124 private:
125 void handleItem(const std::string &Item) {
Stephen Hines3fd0a942011-01-18 12:27:39 -0800126 mContext->addPragma(this->getName(), Item);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700127 mContext->setLicenseNote(Item);
128 }
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800129
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700130 public:
131 RSReflectLicensePragmaHandler(llvm::StringRef Name, RSContext *Context)
132 : RSPragmaHandler(Name, Context) { return; }
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800133
Shih-wei Liaodf5bcce2011-02-28 18:39:23 -0800134 void HandlePragma(clang::Preprocessor &PP,
135 clang::PragmaIntroducerKind Introducer,
136 clang::Token &FirstToken) {
Stephen Hines9d2c0fa2011-01-05 14:55:18 -0800137 this->handleOptionalStringLiteralParamPragma(PP, FirstToken);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700138 }
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800139};
140
Stephen Hines96ab06c2011-01-05 15:29:26 -0800141class RSVersionPragmaHandler : public RSPragmaHandler {
142 private:
143 void handleInt(const int v) {
Stephen Hines3fd0a942011-01-18 12:27:39 -0800144 std::stringstream ss;
145 ss << v;
146 mContext->addPragma(this->getName(), ss.str());
Stephen Hines96ab06c2011-01-05 15:29:26 -0800147 mContext->setVersion(v);
148 }
149
150 public:
151 RSVersionPragmaHandler(llvm::StringRef Name, RSContext *Context)
152 : RSPragmaHandler(Name, Context) { return; }
153
Shih-wei Liaodf5bcce2011-02-28 18:39:23 -0800154 void HandlePragma(clang::Preprocessor &PP,
155 clang::PragmaIntroducerKind Introducer,
156 clang::Token &FirstToken) {
Stephen Hines96ab06c2011-01-05 15:29:26 -0800157 this->handleIntegerParamPragma(PP, FirstToken);
158 }
159};
160
Stephen Hinese639eb52010-11-08 19:27:20 -0800161} // namespace
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700162
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700163RSPragmaHandler *
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700164RSPragmaHandler::CreatePragmaExportTypeHandler(RSContext *Context) {
165 return new RSExportTypePragmaHandler("export_type", Context);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700166}
167
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700168RSPragmaHandler *
169RSPragmaHandler::CreatePragmaJavaPackageNameHandler(RSContext *Context) {
170 return new RSJavaPackageNamePragmaHandler("java_package_name", Context);
Shih-wei Liao537446c2010-06-11 16:05:55 -0700171}
172
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700173RSPragmaHandler *
174RSPragmaHandler::CreatePragmaReflectLicenseHandler(RSContext *Context) {
Stephen Hinesd09df092011-02-03 16:01:12 -0800175 return new RSReflectLicensePragmaHandler("set_reflect_license", Context);
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800176}
177
Stephen Hines96ab06c2011-01-05 15:29:26 -0800178RSPragmaHandler *
179RSPragmaHandler::CreatePragmaVersionHandler(RSContext *Context) {
180 return new RSVersionPragmaHandler("version", Context);
181}
182
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700183void RSPragmaHandler::handleItemListPragma(clang::Preprocessor &PP,
184 clang::Token &FirstToken) {
185 clang::Token &PragmaToken = FirstToken;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700186
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700187 // Skip first token, like "export_var"
188 PP.LexUnexpandedToken(PragmaToken);
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700189
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700190 // Now, the current token must be clang::tok::lpara
191 if (PragmaToken.isNot(clang::tok::l_paren))
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700192 return;
Shih-wei Liao462aefd2010-06-04 15:32:04 -0700193
Loganbe274822011-02-16 22:02:54 +0800194 while (PragmaToken.isNot(clang::tok::eod)) {
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700195 // Lex variable name
196 PP.LexUnexpandedToken(PragmaToken);
197 if (PragmaToken.is(clang::tok::identifier))
zonr6315f762010-10-05 15:35:14 +0800198 this->handleItem(PP.getSpelling(PragmaToken));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700199 else
200 break;
Victor Hsiehc6718b32010-06-23 09:29:44 +0800201
Loganbe274822011-02-16 22:02:54 +0800202 slangAssert(PragmaToken.isNot(clang::tok::eod));
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700203
Victor Hsiehc6718b32010-06-23 09:29:44 +0800204 PP.LexUnexpandedToken(PragmaToken);
205
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700206 if (PragmaToken.isNot(clang::tok::comma))
207 break;
208 }
209 return;
210}
211
zonr6315f762010-10-05 15:35:14 +0800212void RSPragmaHandler::handleNonParamPragma(clang::Preprocessor &PP,
213 clang::Token &FirstToken) {
214 clang::Token &PragmaToken = FirstToken;
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700215
216 // Skip first token, like "export_var_all"
217 PP.LexUnexpandedToken(PragmaToken);
218
219 // Should be end immediately
Loganbe274822011-02-16 22:02:54 +0800220 if (PragmaToken.isNot(clang::tok::eod))
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700221 fprintf(stderr, "RSPragmaHandler::handleNonParamPragma: "
Loganbe274822011-02-16 22:02:54 +0800222 "expected a clang::tok::eod\n");
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700223 return;
224}
225
Stephen Hines9d2c0fa2011-01-05 14:55:18 -0800226void RSPragmaHandler::handleOptionalStringLiteralParamPragma(
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700227 clang::Preprocessor &PP, clang::Token &FirstToken) {
228 clang::Token &PragmaToken = FirstToken;
229
230 // Skip first token, like "set_reflect_license"
231 PP.LexUnexpandedToken(PragmaToken);
232
233 // Now, the current token must be clang::tok::lpara
234 if (PragmaToken.isNot(clang::tok::l_paren))
Victor Hsiehc6718b32010-06-23 09:29:44 +0800235 return;
Victor Hsiehc6718b32010-06-23 09:29:44 +0800236
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700237 // If not ')', eat the following string literal as the license
238 PP.LexUnexpandedToken(PragmaToken);
239 if (PragmaToken.isNot(clang::tok::r_paren)) {
240 // Eat the whole string literal
241 clang::StringLiteralParser StringLiteral(&PragmaToken, 1, PP);
242 if (StringLiteral.hadError)
Stephen Hines9d2c0fa2011-01-05 14:55:18 -0800243 fprintf(stderr, "RSPragmaHandler::handleOptionalStringLiteralParamPragma"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700244 ": illegal string literal\n");
245 else
zonr6315f762010-10-05 15:35:14 +0800246 this->handleItem(std::string(StringLiteral.GetString()));
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800247
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700248 // The current token should be clang::tok::r_para
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800249 PP.LexUnexpandedToken(PragmaToken);
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700250 if (PragmaToken.isNot(clang::tok::r_paren))
Stephen Hines9d2c0fa2011-01-05 14:55:18 -0800251 fprintf(stderr, "RSPragmaHandler::handleOptionalStringLiteralParamPragma"
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700252 ": expected a ')'\n");
253 } else {
254 // If no argument, remove the license
zonr6315f762010-10-05 15:35:14 +0800255 this->handleItem("");
Shih-wei Liao9ef2f782010-10-01 12:31:37 -0700256 }
Victor Hsiehd8a0d182010-07-07 19:22:33 +0800257}
Stephen Hinese639eb52010-11-08 19:27:20 -0800258
Stephen Hines96ab06c2011-01-05 15:29:26 -0800259void RSPragmaHandler::handleIntegerParamPragma(
260 clang::Preprocessor &PP, clang::Token &FirstToken) {
261 clang::Token &PragmaToken = FirstToken;
262
263 // Skip first token, like "version"
264 PP.LexUnexpandedToken(PragmaToken);
265
266 // Now, the current token must be clang::tok::lpara
267 if (PragmaToken.isNot(clang::tok::l_paren))
268 return;
269 PP.LexUnexpandedToken(PragmaToken);
270
271 if (PragmaToken.is(clang::tok::numeric_constant)) {
272 clang::NumericLiteralParser NumericLiteral(PragmaToken.getLiteralData(),
273 PragmaToken.getLiteralData() + PragmaToken.getLength(),
274 PragmaToken.getLocation(), PP);
275 if (NumericLiteral.hadError) {
276 fprintf(stderr, "RSPragmaHandler::handleIntegerParamPragma"
277 ": illegal numeric literal\n");
278 } else {
279 llvm::APInt Val(32, 0);
280 NumericLiteral.GetIntegerValue(Val);
281 this->handleInt(static_cast<int>(Val.getSExtValue()));
282 }
283 PP.LexUnexpandedToken(PragmaToken);
284 } else {
285 // If no argument, set the version to 0
286 this->handleInt(0);
287 }
288
289 if (PragmaToken.isNot(clang::tok::r_paren)) {
290 fprintf(stderr, "RSPragmaHandler::handleIntegerParamPragma"
291 ": expected a ')'\n");
292 }
293
294 do {
295 PP.LexUnexpandedToken(PragmaToken);
Loganbe274822011-02-16 22:02:54 +0800296 } while (PragmaToken.isNot(clang::tok::eod));
Stephen Hines96ab06c2011-01-05 15:29:26 -0800297}
298
Stephen Hinese639eb52010-11-08 19:27:20 -0800299} // namespace slang