1*e221c09eSPhilippe Houdoin /* 2*e221c09eSPhilippe Houdoin * Copyright (c) 2003 Matthijs Hollemans 3*e221c09eSPhilippe Houdoin * 4*e221c09eSPhilippe Houdoin * Permission is hereby granted, free of charge, to any person obtaining a 5*e221c09eSPhilippe Houdoin * copy of this software and associated documentation files (the "Software"), 6*e221c09eSPhilippe Houdoin * to deal in the Software without restriction, including without limitation 7*e221c09eSPhilippe Houdoin * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8*e221c09eSPhilippe Houdoin * and/or sell copies of the Software, and to permit persons to whom the 9*e221c09eSPhilippe Houdoin * Software is furnished to do so, subject to the following conditions: 10*e221c09eSPhilippe Houdoin * 11*e221c09eSPhilippe Houdoin * The above copyright notice and this permission notice shall be included in 12*e221c09eSPhilippe Houdoin * all copies or substantial portions of the Software. 13*e221c09eSPhilippe Houdoin * 14*e221c09eSPhilippe Houdoin * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15*e221c09eSPhilippe Houdoin * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16*e221c09eSPhilippe Houdoin * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17*e221c09eSPhilippe Houdoin * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18*e221c09eSPhilippe Houdoin * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19*e221c09eSPhilippe Houdoin * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20*e221c09eSPhilippe Houdoin * DEALINGS IN THE SOFTWARE. 21*e221c09eSPhilippe Houdoin */ 22*e221c09eSPhilippe Houdoin 23*e221c09eSPhilippe Houdoin %{ 24*e221c09eSPhilippe Houdoin //------------------------------------------------------------------------------ 25*e221c09eSPhilippe Houdoin 26*e221c09eSPhilippe Houdoin #include <stack> 27*e221c09eSPhilippe Houdoin #include <string.h> 28*e221c09eSPhilippe Houdoin 29*e221c09eSPhilippe Houdoin #include "rdef.h" 30*e221c09eSPhilippe Houdoin #include "compile.h" 31*e221c09eSPhilippe Houdoin #include "private.h" 32*e221c09eSPhilippe Houdoin #include "parser.hpp" 33*e221c09eSPhilippe Houdoin 34*e221c09eSPhilippe Houdoin #define LEXERROR(msg) abort_compile(RDEF_COMPILE_ERR, msg); 35*e221c09eSPhilippe Houdoin 36*e221c09eSPhilippe Houdoin // Initial size (and increment) of lexbuf. 37*e221c09eSPhilippe Houdoin #define LEX_BUF_SIZE (64*1024) 38*e221c09eSPhilippe Houdoin 39*e221c09eSPhilippe Houdoin // Temporary buffer that the lexer uses to parse string and raw literals. 40*e221c09eSPhilippe Houdoin // The buffer will grow if necessary, to accommodate large data blocks. 41*e221c09eSPhilippe Houdoin static uint8* lexbuf; 42*e221c09eSPhilippe Houdoin 43*e221c09eSPhilippe Houdoin static uint8* lexptr; // current write position in lexbuf 44*e221c09eSPhilippe Houdoin static size_t lexsize; // current size of the lex buffer 45*e221c09eSPhilippe Houdoin static size_t lexcnt; // how full lexbuf currently is 46*e221c09eSPhilippe Houdoin 47*e221c09eSPhilippe Houdoin static void resetbuf(); // resets lexptr and lexcnt 48*e221c09eSPhilippe Houdoin static void addbuf(uint8); // appends byte to lexbuf 49*e221c09eSPhilippe Houdoin 50*e221c09eSPhilippe Houdoin // When we encounter an #include directive, we push the current 51*e221c09eSPhilippe Houdoin // buffer, filename, and line number on the include stack, so we 52*e221c09eSPhilippe Houdoin // can resume lexing that file when we're done with the include. 53*e221c09eSPhilippe Houdoin struct include_t { 54*e221c09eSPhilippe Houdoin YY_BUFFER_STATE buffer; 55*e221c09eSPhilippe Houdoin char* filename; 56*e221c09eSPhilippe Houdoin int lineno; 57*e221c09eSPhilippe Houdoin }; 58*e221c09eSPhilippe Houdoin 59*e221c09eSPhilippe Houdoin static std::stack<include_t> include_stack; 60*e221c09eSPhilippe Houdoin 61*e221c09eSPhilippe Houdoin static void open_include(); 62*e221c09eSPhilippe Houdoin static void close_include(); 63*e221c09eSPhilippe Houdoin 64*e221c09eSPhilippe Houdoin //------------------------------------------------------------------------------ 65*e221c09eSPhilippe Houdoin %} 66*e221c09eSPhilippe Houdoin 67*e221c09eSPhilippe Houdoin %option noyywrap 68*e221c09eSPhilippe Houdoin %option yylineno 69*e221c09eSPhilippe Houdoin 70*e221c09eSPhilippe Houdoin LETTER [a-zA-Z] 71*e221c09eSPhilippe Houdoin BIN [01] 72*e221c09eSPhilippe Houdoin OCT [0-7] 73*e221c09eSPhilippe Houdoin DEC [0-9] 74*e221c09eSPhilippe Houdoin HEX [0-9a-fA-F] 75*e221c09eSPhilippe Houdoin IDENT [a-zA-Z_][a-zA-Z0-9_]* 76*e221c09eSPhilippe Houdoin WSPACE [ \r\t\n\f] 77*e221c09eSPhilippe Houdoin EXP [eE][+-]?{DEC}+ 78*e221c09eSPhilippe Houdoin 79*e221c09eSPhilippe Houdoin %x COMMENT 80*e221c09eSPhilippe Houdoin %x STRDATA 81*e221c09eSPhilippe Houdoin %x RAWDATA 82*e221c09eSPhilippe Houdoin %x INCLUDE 83*e221c09eSPhilippe Houdoin 84*e221c09eSPhilippe Houdoin %% 85*e221c09eSPhilippe Houdoin 86*e221c09eSPhilippe Houdoin enum return ENUM; 87*e221c09eSPhilippe Houdoin resource return RESOURCE; 88*e221c09eSPhilippe Houdoin array return ARRAY; 89*e221c09eSPhilippe Houdoin message return MESSAGE; 90*e221c09eSPhilippe Houdoin archive return ARCHIVE; 91*e221c09eSPhilippe Houdoin type return RTYPE; 92*e221c09eSPhilippe Houdoin import return IMPORT; 93*e221c09eSPhilippe Houdoin 94*e221c09eSPhilippe Houdoin false yylval.b = false; return BOOL; 95*e221c09eSPhilippe Houdoin true yylval.b = true; return BOOL; 96*e221c09eSPhilippe Houdoin 97*e221c09eSPhilippe Houdoin 0[xX]{HEX}{1,16} { yylval.i = strtoull(yytext + 2, NULL, 16); 98*e221c09eSPhilippe Houdoin return INTEGER; } 99*e221c09eSPhilippe Houdoin 0{OCT}{1,24} { yylval.i = strtoull(yytext, NULL, 8); 100*e221c09eSPhilippe Houdoin return INTEGER; } 101*e221c09eSPhilippe Houdoin 0[bB]{BIN}{1,64} { yylval.i = strtoull(yytext + 2, NULL, 2); 102*e221c09eSPhilippe Houdoin return INTEGER; } 103*e221c09eSPhilippe Houdoin {DEC}+ { yylval.i = strtoull(yytext, NULL, 10); 104*e221c09eSPhilippe Houdoin return INTEGER; } 105*e221c09eSPhilippe Houdoin '....' { yylval.i = (yytext[1] << 24) 106*e221c09eSPhilippe Houdoin | (yytext[2] << 16) 107*e221c09eSPhilippe Houdoin | (yytext[3] << 8) 108*e221c09eSPhilippe Houdoin | yytext[4]; 109*e221c09eSPhilippe Houdoin return INTEGER; } 110*e221c09eSPhilippe Houdoin 111*e221c09eSPhilippe Houdoin {DEC}+{EXP} yylval.f = strtod(yytext, NULL); return FLOAT; 112*e221c09eSPhilippe Houdoin {DEC}*\.{DEC}+{EXP}? yylval.f = strtod(yytext, NULL); return FLOAT; 113*e221c09eSPhilippe Houdoin {DEC}+\.{DEC}*{EXP}? yylval.f = strtod(yytext, NULL); return FLOAT; 114*e221c09eSPhilippe Houdoin 115*e221c09eSPhilippe Houdoin #{DEC}+ { yylval.t = strtoul(yytext + 1, NULL, 10); 116*e221c09eSPhilippe Houdoin return TYPECODE; } 117*e221c09eSPhilippe Houdoin #0[xX]{HEX}{1,8} { yylval.t = strtoul(yytext + 3, NULL, 16); 118*e221c09eSPhilippe Houdoin return TYPECODE; } 119*e221c09eSPhilippe Houdoin #'....' { yylval.t = (yytext[2] << 24) 120*e221c09eSPhilippe Houdoin | (yytext[3] << 16) 121*e221c09eSPhilippe Houdoin | (yytext[4] << 8) 122*e221c09eSPhilippe Houdoin | yytext[5]; 123*e221c09eSPhilippe Houdoin return TYPECODE; } 124*e221c09eSPhilippe Houdoin 125*e221c09eSPhilippe Houdoin {IDENT} { yylval.I = (char*) alloc_mem(yyleng + 1); 126*e221c09eSPhilippe Houdoin memcpy(yylval.I, yytext, yyleng + 1); 127*e221c09eSPhilippe Houdoin return IDENT; } 128*e221c09eSPhilippe Houdoin 129*e221c09eSPhilippe Houdoin \" BEGIN(STRDATA); resetbuf(); 130*e221c09eSPhilippe Houdoin <STRDATA>\"{WSPACE}+\" /* concatenate two literals */ 131*e221c09eSPhilippe Houdoin <STRDATA>\" { BEGIN(INITIAL); 132*e221c09eSPhilippe Houdoin addbuf('\0'); 133*e221c09eSPhilippe Houdoin yylval.d.type = get_type("string"); 134*e221c09eSPhilippe Houdoin yylval.d.size = lexcnt; 135*e221c09eSPhilippe Houdoin yylval.d.ptr = alloc_mem(lexcnt); 136*e221c09eSPhilippe Houdoin memcpy(yylval.d.ptr, lexbuf, lexcnt); 137*e221c09eSPhilippe Houdoin return STRING; } 138*e221c09eSPhilippe Houdoin <STRDATA>\n LEXERROR("string not terminated") 139*e221c09eSPhilippe Houdoin <STRDATA>\\{OCT}{3} addbuf(strtol(yytext + 1, NULL, 8)); 140*e221c09eSPhilippe Houdoin <STRDATA>\\0[xX]{HEX}{2} addbuf(strtol(yytext + 3, NULL, 16)); 141*e221c09eSPhilippe Houdoin <STRDATA>\\[xX]{HEX}{2} addbuf(strtol(yytext + 2, NULL, 16)); 142*e221c09eSPhilippe Houdoin <STRDATA>\\b addbuf('\b'); 143*e221c09eSPhilippe Houdoin <STRDATA>\\f addbuf('\f'); 144*e221c09eSPhilippe Houdoin <STRDATA>\\n addbuf('\n'); 145*e221c09eSPhilippe Houdoin <STRDATA>\\r addbuf('\r'); 146*e221c09eSPhilippe Houdoin <STRDATA>\\t addbuf('\t'); 147*e221c09eSPhilippe Houdoin <STRDATA>\\v addbuf('\v'); 148*e221c09eSPhilippe Houdoin <STRDATA>\\0 addbuf('\0'); 149*e221c09eSPhilippe Houdoin <STRDATA>\\. addbuf(yytext[1]); 150*e221c09eSPhilippe Houdoin <STRDATA>. addbuf(yytext[0]); 151*e221c09eSPhilippe Houdoin 152*e221c09eSPhilippe Houdoin $\" BEGIN(RAWDATA); resetbuf(); 153*e221c09eSPhilippe Houdoin <RAWDATA>\"{WSPACE}+$\" /* concatenate two literals */ 154*e221c09eSPhilippe Houdoin <RAWDATA>\" { BEGIN(INITIAL); 155*e221c09eSPhilippe Houdoin yylval.d.type = get_type("raw"); 156*e221c09eSPhilippe Houdoin yylval.d.size = lexcnt; 157*e221c09eSPhilippe Houdoin yylval.d.ptr = alloc_mem(lexcnt); 158*e221c09eSPhilippe Houdoin memcpy(yylval.d.ptr, lexbuf, lexcnt); 159*e221c09eSPhilippe Houdoin return RAW; } 160*e221c09eSPhilippe Houdoin <RAWDATA>\n LEXERROR("raw data not terminated") 161*e221c09eSPhilippe Houdoin <RAWDATA>{HEX}{2} addbuf(strtol(yytext, NULL, 16)); 162*e221c09eSPhilippe Houdoin <RAWDATA>{HEX} LEXERROR("number of characters must be even") 163*e221c09eSPhilippe Houdoin <RAWDATA>. LEXERROR("invalid character in raw data") 164*e221c09eSPhilippe Houdoin 165*e221c09eSPhilippe Houdoin "/*" BEGIN(COMMENT); /* eat multi-line comment */ 166*e221c09eSPhilippe Houdoin <COMMENT>[^*\n]* /* eat anything that is not a '*' */ 167*e221c09eSPhilippe Houdoin <COMMENT>"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */ 168*e221c09eSPhilippe Houdoin <COMMENT>\n 169*e221c09eSPhilippe Houdoin <COMMENT>"*"+"/" BEGIN(INITIAL); 170*e221c09eSPhilippe Houdoin <COMMENT><<EOF>> LEXERROR("forgot to close /*..*/ comment") 171*e221c09eSPhilippe Houdoin 172*e221c09eSPhilippe Houdoin "//"[^\n]* /* eat single-line comment */ 173*e221c09eSPhilippe Houdoin {WSPACE}+ /* eat whitespace */ 174*e221c09eSPhilippe Houdoin 175*e221c09eSPhilippe Houdoin \#include[ \t]+\" BEGIN(INCLUDE); 176*e221c09eSPhilippe Houdoin <INCLUDE>[ \t]* /* eat the whitespace */ 177*e221c09eSPhilippe Houdoin <INCLUDE>[^ \t\n\"]+\" open_include(); 178*e221c09eSPhilippe Houdoin <INCLUDE>\n LEXERROR("error in include statement") 179*e221c09eSPhilippe Houdoin <INCLUDE><<EOF>> LEXERROR("error in include statement") 180*e221c09eSPhilippe Houdoin <<EOF>> { if (include_stack.empty()) 181*e221c09eSPhilippe Houdoin yyterminate(); 182*e221c09eSPhilippe Houdoin else 183*e221c09eSPhilippe Houdoin close_include(); } 184*e221c09eSPhilippe Houdoin 185*e221c09eSPhilippe Houdoin . return yytext[0]; 186*e221c09eSPhilippe Houdoin 187*e221c09eSPhilippe Houdoin %% 188*e221c09eSPhilippe Houdoin //------------------------------------------------------------------------------ 189*e221c09eSPhilippe Houdoin 190*e221c09eSPhilippe Houdoin void 191*e221c09eSPhilippe Houdoin resetbuf() 192*e221c09eSPhilippe Houdoin { 193*e221c09eSPhilippe Houdoin lexptr = lexbuf; 194*e221c09eSPhilippe Houdoin lexcnt = 0; 195*e221c09eSPhilippe Houdoin } 196*e221c09eSPhilippe Houdoin 197*e221c09eSPhilippe Houdoin 198*e221c09eSPhilippe Houdoin void 199*e221c09eSPhilippe Houdoin addbuf(uint8 b) 200*e221c09eSPhilippe Houdoin { 201*e221c09eSPhilippe Houdoin if (lexcnt == lexsize) { 202*e221c09eSPhilippe Houdoin lexsize += LEX_BUF_SIZE; 203*e221c09eSPhilippe Houdoin lexbuf = (uint8*) realloc(lexbuf, lexsize); 204*e221c09eSPhilippe Houdoin if (lexbuf == NULL) 205*e221c09eSPhilippe Houdoin abort_compile(B_NO_MEMORY, "out of memory"); 206*e221c09eSPhilippe Houdoin 207*e221c09eSPhilippe Houdoin lexptr = lexbuf + lexcnt; 208*e221c09eSPhilippe Houdoin } 209*e221c09eSPhilippe Houdoin 210*e221c09eSPhilippe Houdoin *lexptr++ = b; 211*e221c09eSPhilippe Houdoin ++lexcnt; 212*e221c09eSPhilippe Houdoin } 213*e221c09eSPhilippe Houdoin 214*e221c09eSPhilippe Houdoin 215*e221c09eSPhilippe Houdoin void 216*e221c09eSPhilippe Houdoin open_include() 217*e221c09eSPhilippe Houdoin { 218*e221c09eSPhilippe Houdoin yytext[yyleng - 1] = '\0'; // remove trailing " quote 219*e221c09eSPhilippe Houdoin 220*e221c09eSPhilippe Houdoin char tmpname[B_PATH_NAME_LENGTH]; 221*e221c09eSPhilippe Houdoin if (open_file_from_include_dir(yytext, tmpname)) { 222*e221c09eSPhilippe Houdoin yyin = fopen(tmpname, "r"); 223*e221c09eSPhilippe Houdoin if (yyin != NULL) { 224*e221c09eSPhilippe Houdoin include_t incl; 225*e221c09eSPhilippe Houdoin incl.buffer = YY_CURRENT_BUFFER; 226*e221c09eSPhilippe Houdoin incl.lineno = yylineno; 227*e221c09eSPhilippe Houdoin incl.filename = strdup(lexfile); 228*e221c09eSPhilippe Houdoin include_stack.push(incl); 229*e221c09eSPhilippe Houdoin 230*e221c09eSPhilippe Houdoin strcpy(lexfile, tmpname); 231*e221c09eSPhilippe Houdoin yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); 232*e221c09eSPhilippe Houdoin yylineno = 1; 233*e221c09eSPhilippe Houdoin 234*e221c09eSPhilippe Houdoin BEGIN(INITIAL); 235*e221c09eSPhilippe Houdoin return; 236*e221c09eSPhilippe Houdoin } 237*e221c09eSPhilippe Houdoin } 238*e221c09eSPhilippe Houdoin 239*e221c09eSPhilippe Houdoin abort_compile(RDEF_COMPILE_ERR, "cannot open include %s", yytext); 240*e221c09eSPhilippe Houdoin } 241*e221c09eSPhilippe Houdoin 242*e221c09eSPhilippe Houdoin 243*e221c09eSPhilippe Houdoin void 244*e221c09eSPhilippe Houdoin close_include() 245*e221c09eSPhilippe Houdoin { 246*e221c09eSPhilippe Houdoin fclose(yyin); 247*e221c09eSPhilippe Houdoin yy_delete_buffer(YY_CURRENT_BUFFER); 248*e221c09eSPhilippe Houdoin 249*e221c09eSPhilippe Houdoin include_t incl = include_stack.top(); 250*e221c09eSPhilippe Houdoin include_stack.pop(); 251*e221c09eSPhilippe Houdoin 252*e221c09eSPhilippe Houdoin yy_switch_to_buffer(incl.buffer); 253*e221c09eSPhilippe Houdoin yylineno = incl.lineno; 254*e221c09eSPhilippe Houdoin strcpy(lexfile, incl.filename); 255*e221c09eSPhilippe Houdoin 256*e221c09eSPhilippe Houdoin free(incl.filename); 257*e221c09eSPhilippe Houdoin } 258*e221c09eSPhilippe Houdoin 259*e221c09eSPhilippe Houdoin 260*e221c09eSPhilippe Houdoin void 261*e221c09eSPhilippe Houdoin init_lexer() 262*e221c09eSPhilippe Houdoin { 263*e221c09eSPhilippe Houdoin lexsize = LEX_BUF_SIZE; 264*e221c09eSPhilippe Houdoin lexbuf = (uint8*) malloc(lexsize); 265*e221c09eSPhilippe Houdoin if (lexbuf == NULL) 266*e221c09eSPhilippe Houdoin abort_compile(B_NO_MEMORY, "out of memory"); 267*e221c09eSPhilippe Houdoin 268*e221c09eSPhilippe Houdoin yyrestart(yyin); // necessary for multiple input files 269*e221c09eSPhilippe Houdoin yylineno = 1; 270*e221c09eSPhilippe Houdoin } 271*e221c09eSPhilippe Houdoin 272*e221c09eSPhilippe Houdoin 273*e221c09eSPhilippe Houdoin void 274*e221c09eSPhilippe Houdoin clean_up_lexer() 275*e221c09eSPhilippe Houdoin { 276*e221c09eSPhilippe Houdoin while (!include_stack.empty()) { 277*e221c09eSPhilippe Houdoin close_include(); 278*e221c09eSPhilippe Houdoin } 279*e221c09eSPhilippe Houdoin 280*e221c09eSPhilippe Houdoin if (stdin != yyin) 281*e221c09eSPhilippe Houdoin fclose(yyin); 282*e221c09eSPhilippe Houdoin yy_delete_buffer(YY_CURRENT_BUFFER); 283*e221c09eSPhilippe Houdoin 284*e221c09eSPhilippe Houdoin free(lexbuf); 285*e221c09eSPhilippe Houdoin } 286*e221c09eSPhilippe Houdoin 287