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; }
84in              { SET_BUFFER(IN); return IN; }
85out             { SET_BUFFER(OUT); return OUT; }
86inout           { SET_BUFFER(INOUT); return INOUT; }
87oneway          { SET_BUFFER(ONEWAY); return ONEWAY; }
88
89{brackets}+     { SET_BUFFER(ARRAY); return ARRAY; }
90
91{identifier}                                        { SET_BUFFER(IDENTIFIER); return IDENTIFIER; }
92{identifier}\<{whitespace}*{identifier}({whitespace}*,{whitespace}*{identifier})*{whitespace}*\>    {
93                                                      SET_BUFFER(GENERIC); return GENERIC; }
94
95    /* syntax error! */
96.               { printf("UNKNOWN(%s)", yytext);
97                  yylval.buffer.lineno = yylineno;
98                  yylval.buffer.token = IDENTIFIER;
99                  yylval.buffer.data = strdup(yytext);
100                  return IDENTIFIER;
101                }
102
103%%
104
105// comment and whitespace handling
106// ================================================
107extra_text_type* g_extraText = NULL;
108extra_text_type* g_nextExtraText = NULL;
109
110void begin_extra_text(unsigned lineno, which_extra_text which)
111{
112    extra_text_type* text = (extra_text_type*)malloc(sizeof(extra_text_type));
113    text->lineno = lineno;
114    text->which = which;
115    text->data = NULL;
116    text->len = 0;
117    text->next = NULL;
118    if (g_nextExtraText == NULL) {
119        g_extraText = text;
120    } else {
121        g_nextExtraText->next = text;
122    }
123    g_nextExtraText = text;
124}
125
126void append_extra_text(char* text)
127{
128    if (g_nextExtraText->data == NULL) {
129        g_nextExtraText->data = strdup(text);
130        g_nextExtraText->len = strlen(text);
131    } else {
132        char* orig = g_nextExtraText->data;
133        unsigned oldLen = g_nextExtraText->len;
134        unsigned len = strlen(text);
135        g_nextExtraText->len += len;
136        g_nextExtraText->data = (char*)malloc(g_nextExtraText->len+1);
137        memcpy(g_nextExtraText->data, orig, oldLen);
138        memcpy(g_nextExtraText->data+oldLen, text, len);
139        g_nextExtraText->data[g_nextExtraText->len] = '\0';
140        free(orig);
141    }
142}
143
144extra_text_type*
145get_extra_text(void)
146{
147    extra_text_type* result = g_extraText;
148    g_extraText = NULL;
149    g_nextExtraText = NULL;
150    return result;
151}
152
153void drop_extra_text(void)
154{
155    extra_text_type* p = g_extraText;
156    while (p) {
157        extra_text_type* next = p->next;
158        free(p->data);
159        free(p);
160        free(next);
161    }
162    g_extraText = NULL;
163    g_nextExtraText = NULL;
164}
165
166
167// package handling
168// ================================================
169void do_package_statement(const char* importText)
170{
171    if (g_currentPackage) free((void*)g_currentPackage);
172    g_currentPackage = parse_import_statement(importText);
173}
174
175
176// main parse function
177// ================================================
178char const* g_currentFilename = NULL;
179char const* g_currentPackage = NULL;
180
181int yyparse(void);
182
183int parse_aidl(char const *filename)
184{
185    yyin = fopen(filename, "r");
186    if (yyin) {
187        char const* oldFilename = g_currentFilename;
188        char const* oldPackage = g_currentPackage;
189        g_currentFilename = strdup(filename);
190
191        g_error = 0;
192        yylineno = 1;
193        int rv = yyparse();
194        if (g_error != 0) {
195            rv = g_error;
196        }
197
198        free((void*)g_currentFilename);
199        g_currentFilename = oldFilename;
200
201        if (g_currentPackage) free((void*)g_currentPackage);
202        g_currentPackage = oldPackage;
203
204        return rv;
205    } else {
206        fprintf(stderr, "aidl: unable to open file for read: %s\n", filename);
207        return 1;
208    }
209}
210
211