| %{ |
| #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}?\] |
| |
| %% |
| |
| |
| \%\%\{ { 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 ','; } |
| |
| /* 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; } |
| |
| {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; |
| } |
| } |
| |