%{ /* * Copyright © 2009 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include "main/glheader.h" #include "prog_instruction.h" #include "program_parser.h" #include "program_parse.tab.h" #define require_ARB_vp (yyextra->mode == ARB_vertex) #define require_ARB_fp (yyextra->mode == ARB_fragment) #define require_shadow (yyextra->option.Shadow) #define require_rect (yyextra->option.TexRect) #define require_texarray (yyextra->option.TexArray) #define return_token_or_IDENTIFIER(condition, token) \ do { \ if (condition) { \ return token; \ } else { \ yylval->string = strdup(yytext); \ return IDENTIFIER; \ } \ } while (0) #define return_token_or_DOT(condition, token) \ do { \ if (condition) { \ return token; \ } else { \ yyless(1); \ return DOT; \ } \ } while (0) #define return_opcode(condition, token, opcode, sat) \ do { \ if (condition) { \ yylval->temp_inst.Opcode = OPCODE_ ## opcode; \ yylval->temp_inst.SaturateMode = SATURATE_ ## sat; \ return token; \ } else { \ yylval->string = strdup(yytext); \ return IDENTIFIER; \ } \ } while (0) #define SWIZZLE_INVAL MAKE_SWIZZLE4(SWIZZLE_NIL, SWIZZLE_NIL, \ SWIZZLE_NIL, SWIZZLE_NIL) static unsigned mask_from_char(char c) { switch (c) { case 'x': case 'r': return WRITEMASK_X; case 'y': case 'g': return WRITEMASK_Y; case 'z': case 'b': return WRITEMASK_Z; case 'w': case 'a': return WRITEMASK_W; } return 0; } static unsigned swiz_from_char(char c) { switch (c) { case 'x': case 'r': return SWIZZLE_X; case 'y': case 'g': return SWIZZLE_Y; case 'z': case 'b': return SWIZZLE_Z; case 'w': case 'a': return SWIZZLE_W; } return 0; } #define YY_USER_ACTION \ do { \ yylloc->first_column = yylloc->last_column; \ yylloc->last_column += yyleng; \ if ((yylloc->first_line == 1) \ && (yylloc->first_column == 1)) { \ yylloc->position = 1; \ } else { \ yylloc->position += yylloc->last_column - yylloc->first_column; \ } \ } while(0); #define YY_EXTRA_TYPE struct asm_parser_state * %} num [0-9]+ exp [Ee][-+]?[0-9]+ frac "."[0-9]+ dot "."[ \t]* %option bison-bridge bison-locations reentrant noyywrap %% "!!ARBvp1.0" { return ARBvp_10; } "!!ARBfp1.0" { return ARBfp_10; } ADDRESS { yylval->integer = at_address; return_token_or_IDENTIFIER(require_ARB_vp, ADDRESS); } ALIAS { return ALIAS; } ATTRIB { return ATTRIB; } END { return END; } OPTION { return OPTION; } OUTPUT { return OUTPUT; } PARAM { return PARAM; } TEMP { yylval->integer = at_temp; return TEMP; } ABS { return_opcode( 1, VECTOR_OP, ABS, OFF); } ABS_SAT { return_opcode(require_ARB_fp, VECTOR_OP, ABS, ZERO_ONE); } ADD { return_opcode( 1, BIN_OP, ADD, OFF); } ADD_SAT { return_opcode(require_ARB_fp, BIN_OP, ADD, ZERO_ONE); } ARL { return_opcode(require_ARB_vp, ARL, ARL, OFF); } CMP { return_opcode(require_ARB_fp, TRI_OP, CMP, OFF); } CMP_SAT { return_opcode(require_ARB_fp, TRI_OP, CMP, ZERO_ONE); } COS { return_opcode(require_ARB_fp, SCALAR_OP, COS, OFF); } COS_SAT { return_opcode(require_ARB_fp, SCALAR_OP, COS, ZERO_ONE); } DP3 { return_opcode( 1, BIN_OP, DP3, OFF); } DP3_SAT { return_opcode(require_ARB_fp, BIN_OP, DP3, ZERO_ONE); } DP4 { return_opcode( 1, BIN_OP, DP4, OFF); } DP4_SAT { return_opcode(require_ARB_fp, BIN_OP, DP4, ZERO_ONE); } DPH { return_opcode( 1, BIN_OP, DPH, OFF); } DPH_SAT { return_opcode(require_ARB_fp, BIN_OP, DPH, ZERO_ONE); } DST { return_opcode( 1, BIN_OP, DST, OFF); } DST_SAT { return_opcode(require_ARB_fp, BIN_OP, DST, ZERO_ONE); } EX2 { return_opcode( 1, SCALAR_OP, EX2, OFF); } EX2_SAT { return_opcode(require_ARB_fp, SCALAR_OP, EX2, ZERO_ONE); } EXP { return_opcode(require_ARB_vp, SCALAR_OP, EXP, OFF); } FLR { return_opcode( 1, VECTOR_OP, FLR, OFF); } FLR_SAT { return_opcode(require_ARB_fp, VECTOR_OP, FLR, ZERO_ONE); } FRC { return_opcode( 1, VECTOR_OP, FRC, OFF); } FRC_SAT { return_opcode(require_ARB_fp, VECTOR_OP, FRC, ZERO_ONE); } KIL { return_opcode(require_ARB_fp, KIL, KIL, OFF); } LIT { return_opcode( 1, VECTOR_OP, LIT, OFF); } LIT_SAT { return_opcode(require_ARB_fp, VECTOR_OP, LIT, ZERO_ONE); } LG2 { return_opcode( 1, SCALAR_OP, LG2, OFF); } LG2_SAT { return_opcode(require_ARB_fp, SCALAR_OP, LG2, ZERO_ONE); } LOG { return_opcode(require_ARB_vp, SCALAR_OP, LOG, OFF); } LRP { return_opcode(require_ARB_fp, TRI_OP, LRP, OFF); } LRP_SAT { return_opcode(require_ARB_fp, TRI_OP, LRP, ZERO_ONE); } MAD { return_opcode( 1, TRI_OP, MAD, OFF); } MAD_SAT { return_opcode(require_ARB_fp, TRI_OP, MAD, ZERO_ONE); } MAX { return_opcode( 1, BIN_OP, MAX, OFF); } MAX_SAT { return_opcode(require_ARB_fp, BIN_OP, MAX, ZERO_ONE); } MIN { return_opcode( 1, BIN_OP, MIN, OFF); } MIN_SAT { return_opcode(require_ARB_fp, BIN_OP, MIN, ZERO_ONE); } MOV { return_opcode( 1, VECTOR_OP, MOV, OFF); } MOV_SAT { return_opcode(require_ARB_fp, VECTOR_OP, MOV, ZERO_ONE); } MUL { return_opcode( 1, BIN_OP, MUL, OFF); } MUL_SAT { return_opcode(require_ARB_fp, BIN_OP, MUL, ZERO_ONE); } POW { return_opcode( 1, BINSC_OP, POW, OFF); } POW_SAT { return_opcode(require_ARB_fp, BINSC_OP, POW, ZERO_ONE); } RCP { return_opcode( 1, SCALAR_OP, RCP, OFF); } RCP_SAT { return_opcode(require_ARB_fp, SCALAR_OP, RCP, ZERO_ONE); } RSQ { return_opcode( 1, SCALAR_OP, RSQ, OFF); } RSQ_SAT { return_opcode(require_ARB_fp, SCALAR_OP, RSQ, ZERO_ONE); } SCS { return_opcode(require_ARB_fp, SCALAR_OP, SCS, OFF); } SCS_SAT { return_opcode(require_ARB_fp, SCALAR_OP, SCS, ZERO_ONE); } SGE { return_opcode( 1, BIN_OP, SGE, OFF); } SGE_SAT { return_opcode(require_ARB_fp, BIN_OP, SGE, ZERO_ONE); } SIN { return_opcode(require_ARB_fp, SCALAR_OP, SIN, OFF); } SIN_SAT { return_opcode(require_ARB_fp, SCALAR_OP, SIN, ZERO_ONE); } SLT { return_opcode( 1, BIN_OP, SLT, OFF); } SLT_SAT { return_opcode(require_ARB_fp, BIN_OP, SLT, ZERO_ONE); } SUB { return_opcode( 1, BIN_OP, SUB, OFF); } SUB_SAT { return_opcode(require_ARB_fp, BIN_OP, SUB, ZERO_ONE); } SWZ { return_opcode( 1, SWZ, SWZ, OFF); } SWZ_SAT { return_opcode(require_ARB_fp, SWZ, SWZ, ZERO_ONE); } TEX { return_opcode(require_ARB_fp, SAMPLE_OP, TEX, OFF); } TEX_SAT { return_opcode(require_ARB_fp, SAMPLE_OP, TEX, ZERO_ONE); } TXB { return_opcode(require_ARB_fp, SAMPLE_OP, TXB, OFF); } TXB_SAT { return_opcode(require_ARB_fp, SAMPLE_OP, TXB, ZERO_ONE); } TXP { return_opcode(require_ARB_fp, SAMPLE_OP, TXP, OFF); } TXP_SAT { return_opcode(require_ARB_fp, SAMPLE_OP, TXP, ZERO_ONE); } XPD { return_opcode( 1, BIN_OP, XPD, OFF); } XPD_SAT { return_opcode(require_ARB_fp, BIN_OP, XPD, ZERO_ONE); } vertex { return_token_or_IDENTIFIER(require_ARB_vp, VERTEX); } fragment { return_token_or_IDENTIFIER(require_ARB_fp, FRAGMENT); } program { return PROGRAM; } state { return STATE; } result { return RESULT; } {dot}ambient { return AMBIENT; } {dot}attenuation { return ATTENUATION; } {dot}back { return BACK; } {dot}clip { return_token_or_DOT(require_ARB_vp, CLIP); } {dot}color { return COLOR; } {dot}depth { return_token_or_DOT(require_ARB_fp, DEPTH); } {dot}diffuse { return DIFFUSE; } {dot}direction { return DIRECTION; } {dot}emission { return EMISSION; } {dot}env { return ENV; } {dot}eye { return EYE; } {dot}fogcoord { return FOGCOORD; } {dot}fog { return FOG; } {dot}front { return FRONT; } {dot}half { return HALF; } {dot}inverse { return INVERSE; } {dot}invtrans { return INVTRANS; } {dot}light { return LIGHT; } {dot}lightmodel { return LIGHTMODEL; } {dot}lightprod { return LIGHTPROD; } {dot}local { return LOCAL; } {dot}material { return MATERIAL; } {dot}program { return MAT_PROGRAM; } {dot}matrix { return MATRIX; } {dot}matrixindex { return_token_or_DOT(require_ARB_vp, MATRIXINDEX); } {dot}modelview { return MODELVIEW; } {dot}mvp { return MVP; } {dot}normal { return_token_or_DOT(require_ARB_vp, NORMAL); } {dot}object { return OBJECT; } {dot}palette { return PALETTE; } {dot}params { return PARAMS; } {dot}plane { return PLANE; } {dot}point { return_token_or_DOT(require_ARB_vp, POINT); } {dot}pointsize { return_token_or_DOT(require_ARB_vp, POINTSIZE); } {dot}position { return POSITION; } {dot}primary { return PRIMARY; } {dot}projection { return PROJECTION; } {dot}range { return_token_or_DOT(require_ARB_fp, RANGE); } {dot}row { return ROW; } {dot}scenecolor { return SCENECOLOR; } {dot}secondary { return SECONDARY; } {dot}shininess { return SHININESS; } {dot}size { return_token_or_DOT(require_ARB_vp, SIZE); } {dot}specular { return SPECULAR; } {dot}spot { return SPOT; } {dot}texcoord { return TEXCOORD; } {dot}texenv { return_token_or_DOT(require_ARB_fp, TEXENV); } {dot}texgen { return_token_or_DOT(require_ARB_vp, TEXGEN); } {dot}q { return_token_or_DOT(require_ARB_vp, TEXGEN_Q); } {dot}s { return_token_or_DOT(require_ARB_vp, TEXGEN_S); } {dot}t { return_token_or_DOT(require_ARB_vp, TEXGEN_T); } {dot}texture { return TEXTURE; } {dot}transpose { return TRANSPOSE; } {dot}attrib { return_token_or_DOT(require_ARB_vp, VTXATTRIB); } {dot}weight { return_token_or_DOT(require_ARB_vp, WEIGHT); } texture { return_token_or_IDENTIFIER(require_ARB_fp, TEXTURE_UNIT); } 1D { return_token_or_IDENTIFIER(require_ARB_fp, TEX_1D); } 2D { return_token_or_IDENTIFIER(require_ARB_fp, TEX_2D); } 3D { return_token_or_IDENTIFIER(require_ARB_fp, TEX_3D); } CUBE { return_token_or_IDENTIFIER(require_ARB_fp, TEX_CUBE); } RECT { return_token_or_IDENTIFIER(require_ARB_fp && require_rect, TEX_RECT); } SHADOW1D { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow, TEX_SHADOW1D); } SHADOW2D { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow, TEX_SHADOW2D); } SHADOWRECT { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_rect, TEX_SHADOWRECT); } ARRAY1D { return_token_or_IDENTIFIER(require_ARB_fp && require_texarray, TEX_ARRAY1D); } ARRAY2D { return_token_or_IDENTIFIER(require_ARB_fp && require_texarray, TEX_ARRAY2D); } ARRAYSHADOW1D { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_texarray, TEX_ARRAYSHADOW1D); } ARRAYSHADOW2D { return_token_or_IDENTIFIER(require_ARB_fp && require_shadow && require_texarray, TEX_ARRAYSHADOW2D); } [_a-zA-Z$][_a-zA-Z0-9$]* { yylval->string = strdup(yytext); return IDENTIFIER; } ".." { return DOT_DOT; } {num} { yylval->integer = strtol(yytext, NULL, 10); return INTEGER; } {num}?{frac}{exp}? { yylval->real = strtod(yytext, NULL); return REAL; } {num}"."/[^.] { yylval->real = strtod(yytext, NULL); return REAL; } {num}{exp} { yylval->real = strtod(yytext, NULL); return REAL; } {num}"."{exp} { yylval->real = strtod(yytext, NULL); return REAL; } ".xyzw" { yylval->swiz_mask.swizzle = SWIZZLE_NOOP; yylval->swiz_mask.mask = WRITEMASK_XYZW; return MASK4; } ".xy"[zw] { yylval->swiz_mask.swizzle = SWIZZLE_INVAL; yylval->swiz_mask.mask = WRITEMASK_XY | mask_from_char(yytext[3]); return MASK3; } ".xzw" { yylval->swiz_mask.swizzle = SWIZZLE_INVAL; yylval->swiz_mask.mask = WRITEMASK_XZW; return MASK3; } ".yzw" { yylval->swiz_mask.swizzle = SWIZZLE_INVAL; yylval->swiz_mask.mask = WRITEMASK_YZW; return MASK3; } ".x"[yzw] { yylval->swiz_mask.swizzle = SWIZZLE_INVAL; yylval->swiz_mask.mask = WRITEMASK_X | mask_from_char(yytext[2]); return MASK2; } ".y"[zw] { yylval->swiz_mask.swizzle = SWIZZLE_INVAL; yylval->swiz_mask.mask = WRITEMASK_Y | mask_from_char(yytext[2]); return MASK2; } ".zw" { yylval->swiz_mask.swizzle = SWIZZLE_INVAL; yylval->swiz_mask.mask = WRITEMASK_ZW; return MASK2; } "."[xyzw] { const unsigned s = swiz_from_char(yytext[1]); yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(s, s, s, s); yylval->swiz_mask.mask = mask_from_char(yytext[1]); return MASK1; } "."[xyzw]{4} { yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(swiz_from_char(yytext[1]), swiz_from_char(yytext[2]), swiz_from_char(yytext[3]), swiz_from_char(yytext[4])); yylval->swiz_mask.mask = 0; return SWIZZLE; } ".rgba" { yylval->swiz_mask.swizzle = SWIZZLE_NOOP; yylval->swiz_mask.mask = WRITEMASK_XYZW; return_token_or_DOT(require_ARB_fp, MASK4); } ".rg"[ba] { yylval->swiz_mask.swizzle = SWIZZLE_INVAL; yylval->swiz_mask.mask = WRITEMASK_XY | mask_from_char(yytext[3]); return_token_or_DOT(require_ARB_fp, MASK3); } ".rba" { yylval->swiz_mask.swizzle = SWIZZLE_INVAL; yylval->swiz_mask.mask = WRITEMASK_XZW; return_token_or_DOT(require_ARB_fp, MASK3); } ".gba" { yylval->swiz_mask.swizzle = SWIZZLE_INVAL; yylval->swiz_mask.mask = WRITEMASK_YZW; return_token_or_DOT(require_ARB_fp, MASK3); } ".r"[gba] { yylval->swiz_mask.swizzle = SWIZZLE_INVAL; yylval->swiz_mask.mask = WRITEMASK_X | mask_from_char(yytext[2]); return_token_or_DOT(require_ARB_fp, MASK2); } ".g"[ba] { yylval->swiz_mask.swizzle = SWIZZLE_INVAL; yylval->swiz_mask.mask = WRITEMASK_Y | mask_from_char(yytext[2]); return_token_or_DOT(require_ARB_fp, MASK2); } ".ba" { yylval->swiz_mask.swizzle = SWIZZLE_INVAL; yylval->swiz_mask.mask = WRITEMASK_ZW; return_token_or_DOT(require_ARB_fp, MASK2); } "."[gba] { const unsigned s = swiz_from_char(yytext[1]); yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(s, s, s, s); yylval->swiz_mask.mask = mask_from_char(yytext[1]); return_token_or_DOT(require_ARB_fp, MASK1); } ".r" { if (require_ARB_vp) { return TEXGEN_R; } else { yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X); yylval->swiz_mask.mask = WRITEMASK_X; return MASK1; } } "."[rgba]{4} { yylval->swiz_mask.swizzle = MAKE_SWIZZLE4(swiz_from_char(yytext[1]), swiz_from_char(yytext[2]), swiz_from_char(yytext[3]), swiz_from_char(yytext[4])); yylval->swiz_mask.mask = 0; return_token_or_DOT(require_ARB_fp, SWIZZLE); } "." { return DOT; } \n { yylloc->first_line++; yylloc->first_column = 1; yylloc->last_line++; yylloc->last_column = 1; yylloc->position++; } [ \t\r]+ /* eat whitespace */ ; #.*$ /* eat comments */ ; . { return yytext[0]; } %% void _mesa_program_lexer_ctor(void **scanner, struct asm_parser_state *state, const char *string, size_t len) { yylex_init_extra(state, scanner); yy_scan_bytes(string, len, *scanner); } void _mesa_program_lexer_dtor(void *scanner) { yylex_destroy(scanner); }