slang_rs_pragma_handler.cpp revision 35f5b39f0490953f1fe13ef803b43e3ced9a01d9
1/* 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 17#include "slang_rs_pragma_handler.h" 18 19#include <string> 20 21#include "clang/Basic/TokenKinds.h" 22 23#include "clang/Lex/LiteralSupport.h" 24#include "clang/Lex/Preprocessor.h" 25#include "clang/Lex/Token.h" 26 27#include "slang_rs_context.h" 28 29namespace slang { 30 31namespace { // Anonymous namespace 32 33class RSExportTypePragmaHandler : public RSPragmaHandler { 34 private: 35 void handleItem(const std::string &Item) { 36 mContext->addExportType(Item); 37 } 38 39 public: 40 RSExportTypePragmaHandler(llvm::StringRef Name, RSContext *Context) 41 : RSPragmaHandler(Name, Context) { return; } 42 43 void HandlePragma(clang::Preprocessor &PP, clang::Token &FirstToken) { 44 this->handleItemListPragma(PP, FirstToken); 45 } 46}; 47 48class RSJavaPackageNamePragmaHandler : public RSPragmaHandler { 49 public: 50 RSJavaPackageNamePragmaHandler(llvm::StringRef Name, RSContext *Context) 51 : RSPragmaHandler(Name, Context) { return; } 52 53 void HandlePragma(clang::Preprocessor &PP, clang::Token &FirstToken) { 54 // FIXME: Need to validate the extracted package name from pragma. 55 // Currently "all chars" specified in pragma will be treated as package 56 // name. 57 // 58 // 18.1 The Grammar of the Java Programming Language 59 // (http://java.sun.com/docs/books/jls/third_edition/html/syntax.html#18.1) 60 // 61 // CompilationUnit: 62 // [[Annotations] package QualifiedIdentifier ; ] {ImportDeclaration} 63 // {TypeDeclaration} 64 // 65 // QualifiedIdentifier: 66 // Identifier { . Identifier } 67 // 68 // Identifier: 69 // IDENTIFIER 70 // 71 // 3.8 Identifiers 72 // (http://java.sun.com/docs/books/jls/third_edition/html/lexical.html#3.8) 73 // 74 // 75 76 clang::Token &PragmaToken = FirstToken; 77 std::string PackageName; 78 79 // Skip first token, "java_package_name" 80 PP.LexUnexpandedToken(PragmaToken); 81 82 // Now, the current token must be clang::tok::lpara 83 if (PragmaToken.isNot(clang::tok::l_paren)) 84 return; 85 86 while (PragmaToken.isNot(clang::tok::eom)) { 87 // Lex package name 88 PP.LexUnexpandedToken(PragmaToken); 89 90 bool Invalid; 91 std::string Spelling = PP.getSpelling(PragmaToken, &Invalid); 92 if (!Invalid) 93 PackageName.append(Spelling); 94 95 // Pre-mature end (syntax error will be triggered by preprocessor later) 96 if (PragmaToken.is(clang::tok::eom) || PragmaToken.is(clang::tok::eof)) { 97 break; 98 } else { 99 // Next token is ')' (end of paragma) 100 const clang::Token &NextTok = PP.LookAhead(0); 101 if (NextTok.is(clang::tok::r_paren)) { 102 mContext->setReflectJavaPackageName(PackageName); 103 // Lex until meets clang::tok::eom 104 do { 105 PP.LexUnexpandedToken(PragmaToken); 106 } while (PragmaToken.isNot(clang::tok::eom)); 107 break; 108 } 109 } 110 } 111 return; 112 } 113}; 114 115class RSReflectLicensePragmaHandler : public RSPragmaHandler { 116 private: 117 void handleItem(const std::string &Item) { 118 mContext->setLicenseNote(Item); 119 } 120 121 public: 122 RSReflectLicensePragmaHandler(llvm::StringRef Name, RSContext *Context) 123 : RSPragmaHandler(Name, Context) { return; } 124 125 void HandlePragma(clang::Preprocessor &PP, clang::Token &FirstToken) { 126 this->handleOptionalStringLiateralParamPragma(PP, FirstToken); 127 } 128}; 129 130} // namespace 131 132RSPragmaHandler * 133RSPragmaHandler::CreatePragmaExportTypeHandler(RSContext *Context) { 134 return new RSExportTypePragmaHandler("export_type", Context); 135} 136 137RSPragmaHandler * 138RSPragmaHandler::CreatePragmaJavaPackageNameHandler(RSContext *Context) { 139 return new RSJavaPackageNamePragmaHandler("java_package_name", Context); 140} 141 142RSPragmaHandler * 143RSPragmaHandler::CreatePragmaReflectLicenseHandler(RSContext *Context) { 144 return new RSJavaPackageNamePragmaHandler("set_reflect_license", Context); 145} 146 147void RSPragmaHandler::handleItemListPragma(clang::Preprocessor &PP, 148 clang::Token &FirstToken) { 149 clang::Token &PragmaToken = FirstToken; 150 151 // Skip first token, like "export_var" 152 PP.LexUnexpandedToken(PragmaToken); 153 154 // Now, the current token must be clang::tok::lpara 155 if (PragmaToken.isNot(clang::tok::l_paren)) 156 return; 157 158 while (PragmaToken.isNot(clang::tok::eom)) { 159 // Lex variable name 160 PP.LexUnexpandedToken(PragmaToken); 161 if (PragmaToken.is(clang::tok::identifier)) 162 this->handleItem(PP.getSpelling(PragmaToken)); 163 else 164 break; 165 166 assert(PragmaToken.isNot(clang::tok::eom)); 167 168 PP.LexUnexpandedToken(PragmaToken); 169 170 if (PragmaToken.isNot(clang::tok::comma)) 171 break; 172 } 173 return; 174} 175 176void RSPragmaHandler::handleNonParamPragma(clang::Preprocessor &PP, 177 clang::Token &FirstToken) { 178 clang::Token &PragmaToken = FirstToken; 179 180 // Skip first token, like "export_var_all" 181 PP.LexUnexpandedToken(PragmaToken); 182 183 // Should be end immediately 184 if (PragmaToken.isNot(clang::tok::eom)) 185 fprintf(stderr, "RSPragmaHandler::handleNonParamPragma: " 186 "expected a clang::tok::eom\n"); 187 return; 188} 189 190void RSPragmaHandler::handleOptionalStringLiateralParamPragma( 191 clang::Preprocessor &PP, clang::Token &FirstToken) { 192 clang::Token &PragmaToken = FirstToken; 193 194 // Skip first token, like "set_reflect_license" 195 PP.LexUnexpandedToken(PragmaToken); 196 197 // Now, the current token must be clang::tok::lpara 198 if (PragmaToken.isNot(clang::tok::l_paren)) 199 return; 200 201 // If not ')', eat the following string literal as the license 202 PP.LexUnexpandedToken(PragmaToken); 203 if (PragmaToken.isNot(clang::tok::r_paren)) { 204 // Eat the whole string literal 205 clang::StringLiteralParser StringLiteral(&PragmaToken, 1, PP); 206 if (StringLiteral.hadError) 207 fprintf(stderr, "RSPragmaHandler::handleOptionalStringLiateralParamPragma" 208 ": illegal string literal\n"); 209 else 210 this->handleItem(std::string(StringLiteral.GetString())); 211 212 // The current token should be clang::tok::r_para 213 PP.LexUnexpandedToken(PragmaToken); 214 if (PragmaToken.isNot(clang::tok::r_paren)) 215 fprintf(stderr, "RSPragmaHandler::handleOptionalStringLiateralParamPragma" 216 ": expected a ')'\n"); 217 } else { 218 // If no argument, remove the license 219 this->handleItem(""); 220 } 221} 222 223} // namespace slang 224