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