1/* 2 * Copyright (C) 2016 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 17D [0-9] 18L [a-zA-Z_] 19AN [a-zA-Z_0-9] 20H [a-fA-F_0-9] 21E [Ee][+-]?{D}+ 22FS (f|F|l|L) 23IS (u|U|l|L)* 24S [ \t] 25DOT [.] 26PATH ({DOT}|{AN}|\/|-)+ 27ID {L}{AN}* 28 29%{ 30 31#include "AST.h" 32#include "Declaration.h" 33#include "Type.h" 34#include "VarDeclaration.h" 35#include "FunctionDeclaration.h" 36#include "CompositeDeclaration.h" 37#include "Define.h" 38#include "Include.h" 39#include "EnumVarDeclaration.h" 40#include "Note.h" 41#include "TypeDef.h" 42#include "Expression.h" 43 44#include <assert.h> 45#include <utils/Errors.h> 46 47#include "c2hal_y.h" 48 49using namespace android; 50 51int check_type(yyscan_t yyscanner, struct yyguts_t *yyg); 52 53extern int start_token; 54 55extern std::string last_comment; 56 57// :( 58extern int numB; 59extern std::string functionText; 60 61extern std::string defineText; 62extern std::string otherText; 63 64extern bool isOpenGl; 65 66#define YY_USER_ACTION yylloc->first_line = yylineno; 67 68#define ID_UNLESS_OPEN_GL(OPEN_GL_CODE) \ 69 do { \ 70 if (isOpenGl) { \ 71 OPEN_GL_CODE \ 72 } else { \ 73 yylval->str = strdup(yytext); \ 74 return ID; \ 75 } \ 76 } while(0) 77 78#pragma clang diagnostic push 79#pragma clang diagnostic ignored "-Wunused-parameter" 80#pragma clang diagnostic ignored "-Wdeprecated-register" 81#pragma clang diagnostic ignored "-Wregister" 82 83%} 84 85%option yylineno 86%option nounput 87%option noinput 88%option reentrant 89%option bison-bridge 90%option bison-locations 91%option extra-type="android::AST *" 92 93%x COMMENT_STATE 94%x INCLUDE_STATE 95%x COPY_DECL_STATE 96%x FUNCTION_STATE 97%x DEFINE_STATE 98%x DEFINE_SLURP_STATE 99 100%% 101%{ 102 if (start_token) { 103 int token = start_token; 104 start_token = 0; 105 return token; 106 } 107%} 108 109"\n" { /* needed for yylineno to update */ } 110 111\/\*([^*]|\*+[^*\/])*\*+\/ { last_comment = strdup(yytext); } 112 113"//"[^\r\n]* { /* skip C++ style comment */ } 114 115"__BEGIN_DECLS" { /* macro'd 'extern "C" {' if CPP or nothing */ } 116"__END_DECLS" { /* '}' */ } 117 118"__attribute__((__packed__))" { /* ignore */ } 119"__attribute__((packed))" { /* ignore */ } 120"__attribute__((__deprecated__))" { /* ignore */ } 121 122"EGLAPIENTRYP" { ID_UNLESS_OPEN_GL(return '*';); } 123"EGLAPIENTRY" { ID_UNLESS_OPEN_GL(/* actually is nothing on android */); } 124"GL_APIENTRYP" { ID_UNLESS_OPEN_GL(return '*';); } 125"GL_APIENTRY" { ID_UNLESS_OPEN_GL(/* actually is nothing on android */); } 126"GL_APICALL" { ID_UNLESS_OPEN_GL(/* __attribute__((visibility("default"))) */); } 127 128"#include" { BEGIN(INCLUDE_STATE); return INCLUDE; } 129<INCLUDE_STATE>"<" { return '<'; } 130<INCLUDE_STATE>">" { return '>'; } 131<INCLUDE_STATE>"\"" { return '"'; } 132<INCLUDE_STATE>"\n" { BEGIN(INITIAL); } 133<INCLUDE_STATE>{PATH} { yylval->str = strdup(yytext); return INCLUDE_FILE; } 134<INCLUDE_STATE>. { /* ignore other characters */ } 135 136"static"|"inline" { 137 BEGIN(FUNCTION_STATE); 138 functionText = strdup(yytext); 139 numB = 0; 140 } 141<FUNCTION_STATE>[^{}]+ { functionText += yytext; } 142<FUNCTION_STATE>"{" { functionText += yytext; numB += 1;} 143<FUNCTION_STATE>"}" { 144 functionText += yytext; 145 numB -= 1; 146 147 // Will fail if unbalanced brackets in 148 // strings or comments in the function. 149 if (numB <= 0) { 150 BEGIN(INITIAL); 151 yylval->str = strdup(functionText.c_str()); 152 return FUNCTION; 153 } 154 } 155 156"#"{S}*"define" { BEGIN(DEFINE_STATE); return DEFINE; } 157<DEFINE_STATE>{ID} { 158 BEGIN(DEFINE_SLURP_STATE); 159 defineText = ""; 160 yylval->str = strdup(yytext); 161 return ID; 162 } 163<DEFINE_STATE>. { /* ignore other characters */ } 164 165<DEFINE_SLURP_STATE>\/\*([^*]|\*+[^*\/])*\*+\/ { 166 defineText += yytext; 167 } 168<DEFINE_SLURP_STATE>[^\\\n] { defineText += yytext; } 169<DEFINE_SLURP_STATE>"\\\n" { defineText += yytext; } 170<DEFINE_SLURP_STATE>"\n" { 171 BEGIN(INITIAL); 172 yylval->str = strdup(defineText.c_str()); 173 return DEFINE_SLURP; 174 } 175 176"using" { BEGIN(COPY_DECL_STATE); otherText = strdup(yytext); } 177"#"{S}*{L}+ { BEGIN(COPY_DECL_STATE); otherText = strdup(yytext); } 178<COPY_DECL_STATE>\/\*([^*]|\*+[^*\/])*\*+\/ { 179 otherText += yytext; 180 } 181<COPY_DECL_STATE>[^\\\n] { otherText += yytext; } 182<COPY_DECL_STATE>"\\\n" { otherText += yytext; } 183<COPY_DECL_STATE>"\n" { 184 BEGIN(INITIAL); 185 yylval->str = strdup(otherText.c_str()); 186 // decls/macros we want to preserve 187 // in the output, but there is nothing 188 // special to do about them yet 189 return OTHER_STATEMENT; 190 } 191 192"struct" { return STRUCT; } 193"union" { return UNION; } 194"enum" { return ENUM; } 195"class" { return CLASS; } 196"const" { return CONST; } 197"typedef" { return TYPEDEF; } 198"void" { return VOID; } 199"unsigned" { return UNSIGNED; } 200"signed" { return SIGNED; } 201"namespace" { return NAMESPACE; } 202"extern" { return EXTERN; } 203"\"C\"" { return C_STRING; } 204 205{ID} { yylval->str = strdup(yytext); return ID; } 2060[xX]{H}+{IS}? { yylval->str = strdup(yytext); return INTEGRAL_VALUE; } 2070{D}+{IS}? { yylval->str = strdup(yytext); return INTEGRAL_VALUE; } 208{D}+{IS}? { yylval->str = strdup(yytext); return INTEGRAL_VALUE; } 209 210{D}+{E}{FS}? { yylval->str = strdup(yytext); return VALUE; } 211{D}+\.{E}?{FS}? { yylval->str = strdup(yytext); return VALUE; } 212{D}*\.{D}+{E}?{FS}? { yylval->str = strdup(yytext); return VALUE; } 213L?\"(\\.|[^\\"])*\" { yylval->str = strdup(yytext); return VALUE; } 214 215"(" { return '('; } 216")" { return ')'; } 217"<" { return '<'; } 218">" { return '>'; } 219"{" { return '{'; } 220"}" { return '}'; } 221"[" { return '['; } 222"]" { return ']'; } 223"?" { return '?'; } 224":" { return ':'; } 225"*" { return '*'; } 226";" { return ';'; } 227"," { return ','; } 228"=" { return '='; } 229"+" { return '+'; } 230"-" { return '-'; } 231"/" { return '/'; } 232"%" { return '%'; } 233"&" { return '&'; } 234"|" { return '|'; } 235"^" { return '^'; } 236"~" { return '~'; } 237"<<" { return LSHIFT; } 238">>" { return RSHIFT; } 239 240"..." { return VARARGS; } 241 242. { /* ignore other characters */ } 243 244%% 245 246#pragma clang diagnostic pop 247 248// allows us to specify what start symbol will be used in the grammar 249int start_token; 250bool should_report_errors; 251 252std::string last_comment; 253 254// this is so frowned upon on so many levels, but here vars are so that we can 255// slurp up function text as a string and don't have to implement 256// the *entire* grammar of C (and C++ in some files) just to parse headers 257int numB; 258std::string functionText; 259 260std::string defineText; 261std::string otherText; 262 263bool isOpenGl; 264 265int yywrap(yyscan_t) { 266 return 1; 267} 268 269status_t parseFile(AST *ast) { 270 FILE *file = fopen(ast->getFilename().c_str(), "rb"); 271 272 if (file == NULL) { 273 return -errno; 274 } 275 276 start_token = START_HEADER; 277 isOpenGl = ast->isOpenGl(); 278 should_report_errors = true; 279 280 yyscan_t scanner; 281 yylex_init_extra(ast, &scanner); 282 ast->setScanner(scanner); 283 284 yyset_in(file, scanner); 285 int res = yyparse(ast); 286 287 yylex_destroy(scanner); 288 ast->setScanner(NULL); 289 290 fclose(file); 291 file = NULL; 292 293 return res; 294} 295 296status_t parseExpression(AST *ast, std::string str) { 297 start_token = START_EXPR; 298 isOpenGl = ast->isOpenGl(); 299 should_report_errors = false; 300 301 yyscan_t scanner; 302 yylex_init_extra(ast, &scanner); 303 ast->setScanner(scanner); 304 305 YY_BUFFER_STATE buf = yy_scan_string(str.c_str(), scanner); 306 307 int res = yyparse(ast); 308 309 yy_delete_buffer(buf, scanner); 310 311 yylex_destroy(scanner); 312 ast->setScanner(NULL); 313 314 return res; 315} 316