diff options
-rw-r--r-- | tools/aidl/aidl.cpp | 4 | ||||
-rw-r--r-- | tools/aidl/aidl_language.cpp | 90 | ||||
-rw-r--r-- | tools/aidl/aidl_language.h | 36 | ||||
-rw-r--r-- | tools/aidl/aidl_language_l.l | 62 | ||||
-rw-r--r-- | tools/aidl/aidl_language_y.y | 63 | ||||
-rw-r--r-- | tools/aidl/macros.h | 8 |
6 files changed, 180 insertions, 83 deletions
diff --git a/tools/aidl/aidl.cpp b/tools/aidl/aidl.cpp index 46c689970dc4..d5815011ef4c 100644 --- a/tools/aidl/aidl.cpp +++ b/tools/aidl/aidl.cpp @@ -36,6 +36,8 @@ using std::set; using std::string; using std::vector; +ParseState *psGlobal; + static void test_document(document_item_type* d) { @@ -114,7 +116,7 @@ main_import_parsed(buffer_type* statement) { import_info* import = (import_info*)malloc(sizeof(import_info)); memset(import, 0, sizeof(import_info)); - import->from = strdup(g_currentFilename); + import->from = strdup(psGlobal->FileName().c_str()); import->statement.lineno = statement->lineno; import->statement.data = strdup(statement->data); import->statement.extra = NULL; diff --git a/tools/aidl/aidl_language.cpp b/tools/aidl/aidl_language.cpp index 5fab6c26431a..525292055755 100644 --- a/tools/aidl/aidl_language.cpp +++ b/tools/aidl/aidl_language.cpp @@ -1,20 +1,86 @@ #include "aidl_language.h" #include <stdio.h> -#include <string.h> #include <stdlib.h> +#include <string> +#include <iostream> -#ifdef _WIN32 -int isatty(int fd) -{ - return (fd == 0); +using std::string; +using std::cerr; +using std::endl; + +ParserCallbacks* g_callbacks = NULL; // &k_parserCallbacks; + +void yylex_init(void **); +void yylex_destroy(void *); +void yyset_in(FILE *f, void *); +int yyparse(ParseState*); + +ParseState::ParseState() : ParseState("") {} + +ParseState::ParseState(const string& filename) + : filename_(filename) { + yylex_init(&scanner_); } -#endif -#if 0 -ParserCallbacks k_parserCallbacks = { - NULL -}; -#endif +ParseState::~ParseState() { + yylex_destroy(scanner_); +} -ParserCallbacks* g_callbacks = NULL; // &k_parserCallbacks; +string ParseState::FileName() { + return filename_; +} + +string ParseState::Package() { + return g_currentPackage; +} + +void ParseState::ProcessDocument(const document_item_type& items) { + /* The cast is not my fault. I didn't write the code on the other side. */ + /* TODO(sadmac): b/23977313 */ + g_callbacks->document((document_item_type *)&items); +} + +void ParseState::ProcessImport(const buffer_type& statement) { + /* The cast is not my fault. I didn't write the code on the other side. */ + /* TODO(sadmac): b/23977313 */ + g_callbacks->import((buffer_type *)&statement); +} +void ParseState::ReportError(const string& err) { + /* FIXME: We're printing out the line number as -1. We used to use yylineno + * (which was NEVER correct even before reentrant parsing). Now we'll need + * another way. + */ + cerr << filename_ << ":" << -1 << ": " << err << endl; + error_ = 1; +} + +bool ParseState::FoundNoErrors() { + return error_ == 0; +} + +void *ParseState::Scanner() { + return scanner_; +} + +bool ParseState::OpenFileFromDisk() { + FILE *in = fopen(FileName().c_str(), "r"); + + if (! in) + return false; + + yyset_in(in, Scanner()); + return true; +} + +int ParseState::RunParser() { + int ret = yyparse(this); + + free((void *)g_currentPackage); + g_currentPackage = NULL; + + if (error_) + return 1; + + return ret; +} diff --git a/tools/aidl/aidl_language.h b/tools/aidl/aidl_language.h index a3b1efcbaf40..f3a126e9f57a 100644 --- a/tools/aidl/aidl_language.h +++ b/tools/aidl/aidl_language.h @@ -1,6 +1,9 @@ #ifndef AIDL_AIDL_LANGUAGE_H_ #define AIDL_AIDL_LANGUAGE_H_ +#include <string> + +#include "macros.h" typedef enum { NO_EXTRA_TEXT = 0, @@ -141,12 +144,6 @@ typedef struct ParserCallbacks { extern ParserCallbacks* g_callbacks; -// true if there was an error parsing, false otherwise -extern int g_error; - -// the name of the file we're currently parsing -extern char const* g_currentFilename; - // the package name for our current file extern char const* g_currentPackage; @@ -157,6 +154,33 @@ typedef enum { void init_buffer_type(buffer_type* buf, int lineno); +class ParseState { + public: + ParseState(); + ParseState(const std::string& filename); + ~ParseState(); + + bool OpenFileFromDisk(); + int RunParser(); + void ReportError(const std::string& err); + + bool FoundNoErrors(); + std::string FileName(); + std::string Package(); + void *Scanner(); + + void ProcessDocument(const document_item_type& items); + void ProcessImport(const buffer_type& statement); + + private: + int error_ = 0; + std::string filename_; + std::string package_; + void *scanner_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(ParseState); +}; + #if __cplusplus } #endif diff --git a/tools/aidl/aidl_language_l.l b/tools/aidl/aidl_language_l.l index aa42f2e9a9fd..953e3709eb66 100644 --- a/tools/aidl/aidl_language_l.l +++ b/tools/aidl/aidl_language_l.l @@ -7,6 +7,13 @@ extern YYSTYPE yylval; +#ifdef _WIN32 +static inline int isatty(int fd) +{ + return 0; +} +#endif + // comment and whitespace handling // these functions save a copy of the buffer static void begin_extra_text(unsigned lineno, which_extra_text which); @@ -20,16 +27,18 @@ static void do_package_statement(const char* importText); #define SET_BUFFER(t) \ do { \ - yylval.buffer.lineno = yylineno; \ - yylval.buffer.token = (t); \ - yylval.buffer.data = strdup(yytext); \ - yylval.buffer.extra = get_extra_text(); \ + yylval->buffer.lineno = yyget_lineno(yyscanner); \ + yylval->buffer.token = (t); \ + yylval->buffer.data = strdup(yytext); \ + yylval->buffer.extra = get_extra_text(); \ } while(0) %} %option yylineno %option noyywrap +%option reentrant +%option bison-bridge %x COPYING LONG_COMMENT @@ -96,9 +105,9 @@ oneway { SET_BUFFER(ONEWAY); return ONEWAY; } /* syntax error! */ . { printf("UNKNOWN(%s)", yytext); - yylval.buffer.lineno = yylineno; - yylval.buffer.token = IDENTIFIER; - yylval.buffer.data = strdup(yytext); + yylval->buffer.lineno = yylineno; + yylval->buffer.token = IDENTIFIER; + yylval->buffer.data = strdup(yytext); return IDENTIFIER; } @@ -177,36 +186,17 @@ void do_package_statement(const char* importText) // main parse function // ================================================ -char const* g_currentFilename = NULL; +extern ParseState *psGlobal; char const* g_currentPackage = NULL; -int yyparse(void); +int parse_aidl(char const *filename) { + ParseState ps(filename); + psGlobal = &ps; -int parse_aidl(char const *filename) -{ - yyin = fopen(filename, "r"); - if (yyin) { - char const* oldFilename = g_currentFilename; - char const* oldPackage = g_currentPackage; - g_currentFilename = strdup(filename); - - g_error = 0; - yylineno = 1; - int rv = yyparse(); - if (g_error != 0) { - rv = g_error; - } - - free((void*)g_currentFilename); - g_currentFilename = oldFilename; - - if (g_currentPackage) free((void*)g_currentPackage); - g_currentPackage = oldPackage; - - return rv; - } else { - fprintf(stderr, "aidl: unable to open file for read: %s\n", filename); - return 1; - } -} + if (!ps.OpenFileFromDisk()) { + fprintf(stderr, "aidl: unable to open file for read: %s\n", filename); + return 1; + } + return ps.RunParser(); +} diff --git a/tools/aidl/aidl_language_y.y b/tools/aidl/aidl_language_y.y index 9c5d10e6892a..90fd58c5353c 100644 --- a/tools/aidl/aidl_language_y.y +++ b/tools/aidl/aidl_language_y.y @@ -4,14 +4,24 @@ #include <stdlib.h> #include <string.h> -int yyerror(char* errstr); -int yylex(void); -extern int yylineno; +int yyerror(ParseState* ps, char* errstr) +{ + ps->ReportError(errstr); + return 1; +} + +int yylex(lexer_type *, void *); static int count_brackets(const char*); +#define YYLEX_PARAM ps->Scanner() + %} +%parse-param { ParseState* ps } + +%pure-parser + %token IMPORT %token PACKAGE %token IDENTIFIER @@ -27,8 +37,8 @@ static int count_brackets(const char*); %% document: - document_items { g_callbacks->document($1.document_item); } - | headers document_items { g_callbacks->document($2.document_item); } + document_items { ps->ProcessDocument(*$1.document_item); } + | headers document_items { ps->ProcessDocument(*$2.document_item); } ; headers: @@ -42,8 +52,8 @@ package: ; imports: - IMPORT { g_callbacks->import(&($1.buffer)); } - | IMPORT imports { g_callbacks->import(&($1.buffer)); } + IMPORT { ps->ProcessImport($1.buffer); } + | IMPORT imports { ps->ProcessImport($1.buffer); } ; document_items: @@ -66,7 +76,8 @@ document_items: } } | document_items error { - fprintf(stderr, "%s:%d: syntax error don't know what to do with \"%s\"\n", g_currentFilename, + fprintf(stderr, "%s:%d: syntax error don't know what to do with \"%s\"\n", + ps->FileName().c_str(), $2.buffer.lineno, $2.buffer.data); $$ = $1; } @@ -84,19 +95,20 @@ parcelable_decl: b->document_item.next = NULL; b->keyword_token = $1.buffer; b->name = $2.buffer; - b->package = g_currentPackage ? strdup(g_currentPackage) : NULL; + b->package = + strdup(ps->Package().c_str()); b->semicolon_token = $3.buffer; b->parcelable = true; $$.user_data = b; } | PARCELABLE ';' { fprintf(stderr, "%s:%d syntax error in parcelable declaration. Expected type name.\n", - g_currentFilename, $1.buffer.lineno); + ps->FileName().c_str(), $1.buffer.lineno); $$.user_data = NULL; } | PARCELABLE error ';' { fprintf(stderr, "%s:%d syntax error in parcelable declaration. Expected type name, saw \"%s\".\n", - g_currentFilename, $2.buffer.lineno, $2.buffer.data); + ps->FileName().c_str(), $2.buffer.lineno, $2.buffer.data); $$.user_data = NULL; } ; @@ -128,7 +140,8 @@ interface_decl: interface_header IDENTIFIER '{' interface_items '}' { interface_type* c = $1.interface_obj; c->name = $2.buffer; - c->package = g_currentPackage ? strdup(g_currentPackage) : NULL; + c->package = + strdup(ps->Package().c_str()); c->open_brace_token = $3.buffer; c->interface_items = $4.interface_item; c->close_brace_token = $5.buffer; @@ -136,12 +149,12 @@ interface_decl: } | INTERFACE error '{' interface_items '}' { fprintf(stderr, "%s:%d: syntax error in interface declaration. Expected type name, saw \"%s\"\n", - g_currentFilename, $2.buffer.lineno, $2.buffer.data); + ps->FileName().c_str(), $2.buffer.lineno, $2.buffer.data); $$.document_item = NULL; } | INTERFACE error '}' { fprintf(stderr, "%s:%d: syntax error in interface declaration. Expected type name, saw \"%s\"\n", - g_currentFilename, $2.buffer.lineno, $2.buffer.data); + ps->FileName().c_str(), $2.buffer.lineno, $2.buffer.data); $$.document_item = NULL; } @@ -163,7 +176,7 @@ interface_items: } | interface_items error ';' { fprintf(stderr, "%s:%d: syntax error before ';' (expected method declaration)\n", - g_currentFilename, $3.buffer.lineno); + ps->FileName().c_str(), $3.buffer.lineno); $$ = $1; } ; @@ -259,7 +272,8 @@ arg_list: } } | error { - fprintf(stderr, "%s:%d: syntax error in parameter list\n", g_currentFilename, $1.buffer.lineno); + fprintf(stderr, "%s:%d: syntax error in parameter list\n", + ps->FileName().c_str(), $1.buffer.lineno); $$.arg = NULL; } ; @@ -279,7 +293,8 @@ arg: type: IDENTIFIER { $$.type.type = $1.buffer; - init_buffer_type(&$$.type.array_token, yylineno); + init_buffer_type(&$$.type.array_token, + $1.buffer.lineno); $$.type.dimension = 0; } | IDENTIFIER ARRAY { @@ -289,13 +304,14 @@ type: } | GENERIC { $$.type.type = $1.buffer; - init_buffer_type(&$$.type.array_token, yylineno); + init_buffer_type(&$$.type.array_token, + $1.buffer.lineno); $$.type.dimension = 0; } ; direction: - { init_buffer_type(&$$.buffer, yylineno); } + { init_buffer_type(&$$.buffer, $$.buffer.lineno); } | IN { $$.buffer = $1.buffer; } | OUT { $$.buffer = $1.buffer; } | INOUT { $$.buffer = $1.buffer; } @@ -306,15 +322,6 @@ direction: #include <ctype.h> #include <stdio.h> -int g_error = 0; - -int yyerror(char* errstr) -{ - fprintf(stderr, "%s:%d: %s\n", g_currentFilename, yylineno, errstr); - g_error = 1; - return 1; -} - void init_buffer_type(buffer_type* buf, int lineno) { buf->lineno = lineno; diff --git a/tools/aidl/macros.h b/tools/aidl/macros.h new file mode 100644 index 000000000000..67b8076404a4 --- /dev/null +++ b/tools/aidl/macros.h @@ -0,0 +1,8 @@ +#ifndef AIDL_MACROS_H_ +#define AIDL_MACROS_H_ + +#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) + +#endif // AIDL_MACROS_H_ |