1 %{
2 #include "aidl_language.h"
3 #include "aidl_language_y.h"
4 #include "search_path.h"
5 #include <string.h>
6 #include <stdlib.h>
7 
8 extern YYSTYPE yylval;
9 
10 // comment and whitespace handling
11 // these functions save a copy of the buffer
12 static void begin_extra_text(unsigned lineno, which_extra_text which);
13 static void append_extra_text(char* text);
14 static extra_text_type* get_extra_text(void);   // you now own the object
15                                                 // this returns
16 static void drop_extra_text(void);
17 
18 // package handling
19 static void do_package_statement(const char* importText);
20 
21 #define SET_BUFFER(t) \
22     do { \
23         yylval.buffer.lineno = yylineno; \
24         yylval.buffer.token = (t); \
25         yylval.buffer.data = strdup(yytext); \
26         yylval.buffer.extra = get_extra_text(); \
27     } while(0)
28 
29 %}
30 
31 %option yylineno
32 %option noyywrap
33 
34 %x COPYING LONG_COMMENT
35 
36 identifier  [_a-zA-Z][_a-zA-Z0-9\.]*
37 whitespace  ([ \t\n\r]+)
38 brackets    \[{whitespace}?\]
39 idvalue     (0|[1-9][0-9]*)
40 
41 %%
42 
43 
44 \%\%\{              { begin_extra_text(yylineno, COPY_TEXT); BEGIN(COPYING); }
45 <COPYING>\}\%\%     { BEGIN(INITIAL); }
46 <COPYING>.*\n       { append_extra_text(yytext); }
47 <COPYING>.*         { append_extra_text(yytext); }
48 <COPYING>\n+        { append_extra_text(yytext); }
49 
50 
51 \/\*                            { begin_extra_text(yylineno, (which_extra_text)LONG_COMMENT);
52                                   BEGIN(LONG_COMMENT); }
53 <LONG_COMMENT>[^*]*             { append_extra_text(yytext); }
54 <LONG_COMMENT>\*+[^/]           { append_extra_text(yytext); }
55 <LONG_COMMENT>\n                { append_extra_text(yytext); }
56 <LONG_COMMENT>\**\/             { BEGIN(INITIAL); }
57 
58 ^{whitespace}?import{whitespace}[^ \t\r\n]+{whitespace}?;  {
59                                                 SET_BUFFER(IMPORT);
60                                                 return IMPORT;
61                                             }
62 ^{whitespace}?package{whitespace}[^ \t\r\n]+{whitespace}?;  {
63                                                 do_package_statement(yytext);
64                                                 SET_BUFFER(PACKAGE);
65                                                 return PACKAGE;
66                                             }
67 <<EOF>>             { yyterminate(); }
68 
69 \/\/.*\n            { begin_extra_text(yylineno, SHORT_COMMENT);
70                         append_extra_text(yytext); }
71 
72 {whitespace}    { /* begin_extra_text(yylineno, WHITESPACE);
73                     append_extra_text(yytext); */ }
74 
75 ;               { SET_BUFFER(';'); return ';'; }
76 \{              { SET_BUFFER('{'); return '{'; }
77 \}              { SET_BUFFER('}'); return '}'; }
78 \(              { SET_BUFFER('('); return '('; }
79 \)              { SET_BUFFER(')'); return ')'; }
80 ,               { SET_BUFFER(','); return ','; }
81 =               { SET_BUFFER('='); return '='; }
82 
83     /* keywords */
84 parcelable      { SET_BUFFER(PARCELABLE); return PARCELABLE; }
85 interface       { SET_BUFFER(INTERFACE); return INTERFACE; }
86 flattenable     { SET_BUFFER(FLATTENABLE); return FLATTENABLE; }
87 rpc             { SET_BUFFER(INTERFACE); return RPC; }
88 in              { SET_BUFFER(IN); return IN; }
89 out             { SET_BUFFER(OUT); return OUT; }
90 inout           { SET_BUFFER(INOUT); return INOUT; }
91 oneway          { SET_BUFFER(ONEWAY); return ONEWAY; }
92 
93 {brackets}+     { SET_BUFFER(ARRAY); return ARRAY; }
94 {idvalue}       { SET_BUFFER(IDVALUE); return IDVALUE; }
95 {identifier}                                        { SET_BUFFER(IDENTIFIER); return IDENTIFIER; }
96 {identifier}\<{whitespace}*{identifier}({whitespace}*,{whitespace}*{identifier})*{whitespace}*\>    {
97                                                       SET_BUFFER(GENERIC); return GENERIC; }
98 
99     /* syntax error! */
100 .               { printf("UNKNOWN(%s)", yytext);
101                   yylval.buffer.lineno = yylineno;
102                   yylval.buffer.token = IDENTIFIER;
103                   yylval.buffer.data = strdup(yytext);
104                   return IDENTIFIER;
105                 }
106 
107 %%
108 
109 // comment and whitespace handling
110 // ================================================
111 extra_text_type* g_extraText = NULL;
112 extra_text_type* g_nextExtraText = NULL;
113 
begin_extra_text(unsigned lineno,which_extra_text which)114 void begin_extra_text(unsigned lineno, which_extra_text which)
115 {
116     extra_text_type* text = (extra_text_type*)malloc(sizeof(extra_text_type));
117     text->lineno = lineno;
118     text->which = which;
119     text->data = NULL;
120     text->len = 0;
121     text->next = NULL;
122     if (g_nextExtraText == NULL) {
123         g_extraText = text;
124     } else {
125         g_nextExtraText->next = text;
126     }
127     g_nextExtraText = text;
128 }
129 
append_extra_text(char * text)130 void append_extra_text(char* text)
131 {
132     if (g_nextExtraText->data == NULL) {
133         g_nextExtraText->data = strdup(text);
134         g_nextExtraText->len = strlen(text);
135     } else {
136         char* orig = g_nextExtraText->data;
137         unsigned oldLen = g_nextExtraText->len;
138         unsigned len = strlen(text);
139         g_nextExtraText->len += len;
140         g_nextExtraText->data = (char*)malloc(g_nextExtraText->len+1);
141         memcpy(g_nextExtraText->data, orig, oldLen);
142         memcpy(g_nextExtraText->data+oldLen, text, len);
143         g_nextExtraText->data[g_nextExtraText->len] = '\0';
144         free(orig);
145     }
146 }
147 
148 extra_text_type*
get_extra_text(void)149 get_extra_text(void)
150 {
151     extra_text_type* result = g_extraText;
152     g_extraText = NULL;
153     g_nextExtraText = NULL;
154     return result;
155 }
156 
drop_extra_text(void)157 void drop_extra_text(void)
158 {
159     extra_text_type* p = g_extraText;
160     while (p) {
161         extra_text_type* next = p->next;
162         free(p->data);
163         free(p);
164         free(next);
165     }
166     g_extraText = NULL;
167     g_nextExtraText = NULL;
168 }
169 
170 
171 // package handling
172 // ================================================
do_package_statement(const char * importText)173 void do_package_statement(const char* importText)
174 {
175     if (g_currentPackage) free((void*)g_currentPackage);
176     g_currentPackage = parse_import_statement(importText);
177 }
178 
179 
180 // main parse function
181 // ================================================
182 char const* g_currentFilename = NULL;
183 char const* g_currentPackage = NULL;
184 
185 int yyparse(void);
186 
parse_aidl(char const * filename)187 int parse_aidl(char const *filename)
188 {
189     yyin = fopen(filename, "r");
190     if (yyin) {
191         char const* oldFilename = g_currentFilename;
192         char const* oldPackage = g_currentPackage;
193         g_currentFilename = strdup(filename);
194 
195         g_error = 0;
196         yylineno = 1;
197         int rv = yyparse();
198         if (g_error != 0) {
199             rv = g_error;
200         }
201 
202         free((void*)g_currentFilename);
203         g_currentFilename = oldFilename;
204 
205         if (g_currentPackage) free((void*)g_currentPackage);
206         g_currentPackage = oldPackage;
207 
208         return rv;
209     } else {
210         fprintf(stderr, "aidl: unable to open file for read: %s\n", filename);
211         return 1;
212     }
213 }
214 
215