%{ #include "aidl_language.h" #include "aidl_language_y.h" #include "search_path.h" #include <string.h> #include <stdlib.h> extern YYSTYPE yylval; // comment and whitespace handling // these functions save a copy of the buffer static void begin_extra_text(unsigned lineno, which_extra_text which); static void append_extra_text(char* text); static extra_text_type* get_extra_text(void); // you now own the object // this returns static void drop_extra_text(void); // package handling 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(); \ } while(0) %} %option yylineno %option noyywrap %x COPYING LONG_COMMENT identifier [_a-zA-Z][_a-zA-Z0-9\.]* whitespace ([ \t\n\r]+) brackets \[{whitespace}?\] idvalue (0|[1-9][0-9]*) %% \%\%\{ { begin_extra_text(yylineno, COPY_TEXT); BEGIN(COPYING); } <COPYING>\}\%\% { BEGIN(INITIAL); } <COPYING>.*\n { append_extra_text(yytext); } <COPYING>.* { append_extra_text(yytext); } <COPYING>\n+ { append_extra_text(yytext); } \/\* { begin_extra_text(yylineno, (which_extra_text)LONG_COMMENT); BEGIN(LONG_COMMENT); } <LONG_COMMENT>[^*]* { append_extra_text(yytext); } <LONG_COMMENT>\*+[^/] { append_extra_text(yytext); } <LONG_COMMENT>\n { append_extra_text(yytext); } <LONG_COMMENT>\**\/ { BEGIN(INITIAL); } ^{whitespace}?import{whitespace}[^ \t\r\n]+{whitespace}?; { SET_BUFFER(IMPORT); return IMPORT; } ^{whitespace}?package{whitespace}[^ \t\r\n]+{whitespace}?; { do_package_statement(yytext); SET_BUFFER(PACKAGE); return PACKAGE; } <<EOF>> { yyterminate(); } \/\/.*\n { begin_extra_text(yylineno, SHORT_COMMENT); append_extra_text(yytext); } {whitespace} { /* begin_extra_text(yylineno, WHITESPACE); append_extra_text(yytext); */ } ; { SET_BUFFER(';'); return ';'; } \{ { SET_BUFFER('{'); return '{'; } \} { SET_BUFFER('}'); return '}'; } \( { SET_BUFFER('('); return '('; } \) { SET_BUFFER(')'); return ')'; } , { SET_BUFFER(','); return ','; } = { SET_BUFFER('='); return '='; } /* keywords */ parcelable { SET_BUFFER(PARCELABLE); return PARCELABLE; } interface { SET_BUFFER(INTERFACE); return INTERFACE; } flattenable { SET_BUFFER(FLATTENABLE); return FLATTENABLE; } rpc { SET_BUFFER(INTERFACE); return RPC; } in { SET_BUFFER(IN); return IN; } out { SET_BUFFER(OUT); return OUT; } inout { SET_BUFFER(INOUT); return INOUT; } oneway { SET_BUFFER(ONEWAY); return ONEWAY; } {brackets}+ { SET_BUFFER(ARRAY); return ARRAY; } {idvalue} { SET_BUFFER(IDVALUE); return IDVALUE; } {identifier} { SET_BUFFER(IDENTIFIER); return IDENTIFIER; } {identifier}\<{whitespace}*{identifier}({whitespace}*,{whitespace}*{identifier})*{whitespace}*\> { SET_BUFFER(GENERIC); return GENERIC; } /* syntax error! */ . { printf("UNKNOWN(%s)", yytext); yylval.buffer.lineno = yylineno; yylval.buffer.token = IDENTIFIER; yylval.buffer.data = strdup(yytext); return IDENTIFIER; } %% // comment and whitespace handling // ================================================ extra_text_type* g_extraText = NULL; extra_text_type* g_nextExtraText = NULL; void begin_extra_text(unsigned lineno, which_extra_text which) { extra_text_type* text = (extra_text_type*)malloc(sizeof(extra_text_type)); text->lineno = lineno; text->which = which; text->data = NULL; text->len = 0; text->next = NULL; if (g_nextExtraText == NULL) { g_extraText = text; } else { g_nextExtraText->next = text; } g_nextExtraText = text; } void append_extra_text(char* text) { if (g_nextExtraText->data == NULL) { g_nextExtraText->data = strdup(text); g_nextExtraText->len = strlen(text); } else { char* orig = g_nextExtraText->data; unsigned oldLen = g_nextExtraText->len; unsigned len = strlen(text); g_nextExtraText->len += len; g_nextExtraText->data = (char*)malloc(g_nextExtraText->len+1); memcpy(g_nextExtraText->data, orig, oldLen); memcpy(g_nextExtraText->data+oldLen, text, len); g_nextExtraText->data[g_nextExtraText->len] = '\0'; free(orig); } } extra_text_type* get_extra_text(void) { extra_text_type* result = g_extraText; g_extraText = NULL; g_nextExtraText = NULL; return result; } void drop_extra_text(void) { extra_text_type* p = g_extraText; while (p) { extra_text_type* next = p->next; free(p->data); free(p); free(next); } g_extraText = NULL; g_nextExtraText = NULL; } // package handling // ================================================ void do_package_statement(const char* importText) { if (g_currentPackage) free((void*)g_currentPackage); g_currentPackage = parse_import_statement(importText); } // main parse function // ================================================ char const* g_currentFilename = NULL; char const* g_currentPackage = NULL; int yyparse(void); 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; } }