2 * Copyright (c) 2003 Matthijs Hollemans
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 * DEALINGS IN THE SOFTWARE.
24 //------------------------------------------------------------------------------
34 #define LEXERROR(msg) abort_compile(RDEF_COMPILE_ERR, msg);
36 // Initial size (and increment) of lexbuf.
37 #define LEX_BUF_SIZE (64*1024)
39 // Temporary buffer that the lexer uses to parse string and raw literals.
40 // The buffer will grow if necessary, to accommodate large data blocks.
43 static uint8* lexptr; // current write position in lexbuf
44 static size_t lexsize; // current size of the lex buffer
45 static size_t lexcnt; // how full lexbuf currently is
47 static void resetbuf(); // resets lexptr and lexcnt
48 static void addbuf(uint8); // appends byte to lexbuf
50 // When we encounter an #include directive, we push the current
51 // buffer, filename, and line number on the include stack, so we
52 // can resume lexing that file when we're done with the include.
54 YY_BUFFER_STATE buffer;
59 static std::stack<include_t> include_stack;
61 static void open_include();
62 static void close_include();
64 //------------------------------------------------------------------------------
75 IDENT [a-zA-Z_][a-zA-Z0-9_]*
87 resource return RESOURCE;
89 message return MESSAGE;
90 archive return ARCHIVE;
94 false yylval.b = false; return BOOL;
95 true yylval.b = true; return BOOL;
97 0[xX]{HEX}{1,16} { yylval.i = strtoull(yytext + 2, NULL, 16);
99 0{OCT}{1,24} { yylval.i = strtoull(yytext, NULL, 8);
101 0[bB]{BIN}{1,64} { yylval.i = strtoull(yytext + 2, NULL, 2);
103 {DEC}+ { yylval.i = strtoull(yytext, NULL, 10);
105 '....' { yylval.i = (yytext[1] << 24)
111 {DEC}+{EXP} yylval.f = strtod(yytext, NULL); return FLOAT;
112 {DEC}*\.{DEC}+{EXP}? yylval.f = strtod(yytext, NULL); return FLOAT;
113 {DEC}+\.{DEC}*{EXP}? yylval.f = strtod(yytext, NULL); return FLOAT;
115 #{DEC}+ { yylval.t = strtoul(yytext + 1, NULL, 10);
117 #0[xX]{HEX}{1,8} { yylval.t = strtoul(yytext + 3, NULL, 16);
119 #'....' { yylval.t = (yytext[2] << 24)
125 {IDENT} { yylval.I = (char*) alloc_mem(yyleng + 1);
126 memcpy(yylval.I, yytext, yyleng + 1);
129 \" BEGIN(STRDATA); resetbuf();
130 <STRDATA>\"{WSPACE}+\" /* concatenate two literals */
131 <STRDATA>\" { BEGIN(INITIAL);
133 yylval.d.type = get_type("string");
134 yylval.d.size = lexcnt;
135 yylval.d.ptr = alloc_mem(lexcnt);
136 memcpy(yylval.d.ptr, lexbuf, lexcnt);
138 <STRDATA>\n LEXERROR("string not terminated")
139 <STRDATA>\\{OCT}{3} addbuf(strtol(yytext + 1, NULL, 8));
140 <STRDATA>\\0[xX]{HEX}{2} addbuf(strtol(yytext + 3, NULL, 16));
141 <STRDATA>\\[xX]{HEX}{2} addbuf(strtol(yytext + 2, NULL, 16));
142 <STRDATA>\\b addbuf('\b');
143 <STRDATA>\\f addbuf('\f');
144 <STRDATA>\\n addbuf('\n');
145 <STRDATA>\\r addbuf('\r');
146 <STRDATA>\\t addbuf('\t');
147 <STRDATA>\\v addbuf('\v');
148 <STRDATA>\\0 addbuf('\0');
149 <STRDATA>\\. addbuf(yytext[1]);
150 <STRDATA>. addbuf(yytext[0]);
152 $\" BEGIN(RAWDATA); resetbuf();
153 <RAWDATA>\"{WSPACE}+$\" /* concatenate two literals */
154 <RAWDATA>\" { BEGIN(INITIAL);
155 yylval.d.type = get_type("raw");
156 yylval.d.size = lexcnt;
157 yylval.d.ptr = alloc_mem(lexcnt);
158 memcpy(yylval.d.ptr, lexbuf, lexcnt);
160 <RAWDATA>\n LEXERROR("raw data not terminated")
161 <RAWDATA>{HEX}{2} addbuf(strtol(yytext, NULL, 16));
162 <RAWDATA>{HEX} LEXERROR("number of characters must be even")
163 <RAWDATA>. LEXERROR("invalid character in raw data")
165 "/*" BEGIN(COMMENT); /* eat multi-line comment */
166 <COMMENT>[^*\n]* /* eat anything that is not a '*' */
167 <COMMENT>"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */
169 <COMMENT>"*"+"/" BEGIN(INITIAL);
170 <COMMENT><<EOF>> LEXERROR("forgot to close /*..*/ comment")
172 "//"[^\n]* /* eat single-line comment */
173 {WSPACE}+ /* eat whitespace */
175 \#include[ \t]+\" BEGIN(INCLUDE);
176 <INCLUDE>[ \t]* /* eat the whitespace */
177 <INCLUDE>[^ \t\n\"]+\" open_include();
178 <INCLUDE>\n LEXERROR("error in include statement")
179 <INCLUDE><<EOF>> LEXERROR("error in include statement")
180 <<EOF>> { if (include_stack.empty())
188 //------------------------------------------------------------------------------
201 if (lexcnt == lexsize) {
202 lexsize += LEX_BUF_SIZE;
203 lexbuf = (uint8*) realloc(lexbuf, lexsize);
205 abort_compile(B_NO_MEMORY, "out of memory");
207 lexptr = lexbuf + lexcnt;
218 yytext[yyleng - 1] = '\0'; // remove trailing " quote
220 char tmpname[B_PATH_NAME_LENGTH];
221 if (open_file_from_include_dir(yytext, tmpname)) {
222 yyin = fopen(tmpname, "r");
225 incl.buffer = YY_CURRENT_BUFFER;
226 incl.lineno = yylineno;
227 incl.filename = strdup(lexfile);
228 include_stack.push(incl);
230 strcpy(lexfile, tmpname);
231 yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
239 abort_compile(RDEF_COMPILE_ERR, "cannot open include %s", yytext);
247 yy_delete_buffer(YY_CURRENT_BUFFER);
249 include_t incl = include_stack.top();
252 yy_switch_to_buffer(incl.buffer);
253 yylineno = incl.lineno;
254 strcpy(lexfile, incl.filename);
263 lexsize = LEX_BUF_SIZE;
264 lexbuf = (uint8*) malloc(lexsize);
266 abort_compile(B_NO_MEMORY, "out of memory");
268 yyrestart(yyin); // necessary for multiple input files
276 while (!include_stack.empty()) {
282 yy_delete_buffer(YY_CURRENT_BUFFER);