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
8extern YYSTYPE yylval;
9
10// comment and whitespace handling
11// these functions save a copy of the buffer
12static void begin_extra_text(unsigned lineno, which_extra_text which);
13static void append_extra_text(char* text);
14static extra_text_type* get_extra_text(void);   // you now own the object
15                                                // this returns
16static void drop_extra_text(void);
17
18// package handling
19static 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
36identifier  [_a-zA-Z][_a-zA-Z0-9\.]*
37whitespace  ([ \t\n\r]+)
38brackets    \[{whitespace}?\]
39idvalue     (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 */
84parcelable      { SET_BUFFER(PARCELABLE); return PARCELABLE; }
85interface       { SET_BUFFER(INTERFACE); return INTERFACE; }
86flattenable     { SET_BUFFER(FLATTENABLE); return FLATTENABLE; }
87rpc             { SET_BUFFER(INTERFACE); return RPC; }
88in              { SET_BUFFER(IN); return IN; }
89out             { SET_BUFFER(OUT); return OUT; }
90inout           { SET_BUFFER(INOUT); return INOUT; }
91oneway          { 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// ================================================
111extra_text_type* g_extraText = NULL;
112extra_text_type* g_nextExtraText = NULL;
113
114void 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
130void 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
148extra_text_type*
149get_extra_text(void)
150{
151    extra_text_type* result = g_extraText;
152    g_extraText = NULL;
153    g_nextExtraText = NULL;
154    return result;
155}
156
157void 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// ================================================
173void 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// ================================================
182char const* g_currentFilename = NULL;
183char const* g_currentPackage = NULL;
184
185int yyparse(void);
186
187int 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